From dbkr at freenetproject.org Tue Jul 11 19:22:05 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Tue, 11 Jul 2006 19:22:05 +0000 (UTC)
Subject: [Freemail] r9564 - in trunk/apps/Freemail: . docs docs/spec
Message-ID: <20060711192205.92C119BEEC@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-11 19:22:02 +0000 (Tue, 11 Jul 2006)
New Revision: 9564
Added:
trunk/apps/Freemail/docs/
trunk/apps/Freemail/docs/spec/
trunk/apps/Freemail/docs/spec/spec.tex
Log:
Add the start of the specfification document
Added: trunk/apps/Freemail/docs/spec/spec.tex
===================================================================
--- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-11 17:44:10 UTC (rev 9563)
+++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-11 19:22:02 UTC (rev 9564)
@@ -0,0 +1,80 @@
+\documentclass[12pt,a4paper]{article}
+\begin{document}
+\title{Freemail - Specification and Protocol Documentation}
+\date{July 2006}
+\maketitle
+
+This is a working draft of the Freemail spcification. All parts of this document are subject to change.
+
+\section{Introduction}
+\subsection{What is Freemail}
+Freemail is an email-like messaging system that transports all messages over Freenet 0.7 in order to achieve anoymity and cencorship-resillience. Its protocol is designed to be as resistant as possible to attacks such as message floods and denial of service.
+
+Freemail uses IMAP and SMTP to interface with standard email clients, making taking advantage of interfaces that people are already accustomed to.
+
+\section{Channel Setup}
+\subsection{Mailsites}
+Before any communication occurs between a sender and a recipient (who, in accordance with cryptography tradition shall be called Alice and Bob, respectively), a channel is setup that is used between those two and only those two parties. This channel comprises a Freenet SSK keypair to which Alice has the private key and Bob has the public key. This permits one-way communication between those two parties - if communication the other way is required, a separate channel is used.
+
+All Freemail users have an Freemail address, which one may give out to others in order to allow them to contact you. From this Freemail address, it is possible to derive a Freenet SSK URI. This is the user's 'mailsite'.
+
+A Freemail address comprises an arbitrary text string, followed by an '@' character. Following this is the mailsite address encoded in base 32 - that is, a valid Freenet uri that points to the mailsite. The string '.freenet' is appended to the whole address. An example Freemail address follows:
+
+bob at KVJUWQCMJ53UI6KEGJKFI2JQIZZFKY3XG4YE4QRSMUYWYV2PLJ4U27TLGR4DI3TLNZXW6QTSJIYCYNKSOR4XK23MGZDS2UDRKVCTITBXJJWDQYKIOFMWC33VONTFOZTQMJZTS5LCONEWGY3WGQWECUKBIJAUCRJPNVQWS3DTNF2GKLZNGEXQ.freemail
+
+The base 32 encoded mailsite in this case is: USK at LOwDyD2TTi0FrUcw70NB2e1lWOZyM~k4x4nknooBrJ0,5Rtyukl6G-PqUE4L7Jl8aHqYaousfWfpbs9ubsIccv4,AQABAAE/mailsite/-1/
+
+(this is liable to change to make the addresses shorter)
+
+Once the mailsite address has been obtained from the Freemail address, the string 'mailpage' is appended to obtain the URI for the mailpage. This mailpage contains all information required to contact the owner. The format of a mailpage is a 'Props File', which is used repeatedly in Freemail as a trivial format for storing short pieces of information. See section \ref{PropsFile}.
+
+\subsection{Mailpages}
+The following pieces of information are required in a mailpage:
+
+\begin{itemize}
+\item rtskey - This is an arbitrary string of alphanumeric characters which is used to derive a KSK that can be used to send messages to the owner of the mailsite.
+\item asymkey.modulus - The modulus of the owner's RSA encryption key, as an integer in base 10.
+\item asymkey.pubexponent - The public exponent of the owner's RSA encruption key, as an integer in base 10.
+\end{itemize}
+
+\subsection{RTS Messages}
+Once Alice has retrieved the recipient's mailpage, she sends an RTS message to Bob. This RTS message is, again, a props file, with the following keys:
+
+\begin{itemize}
+\item commssk - The SSK URI to which messages will be inserted.
+\item messagetype - This should be 'rts', to indicate that this message is an RTS.
+\item to - The Freenet URI that appears encoded in Bob's Freemail address. This is necessary in order to prevent surreptitious forwarding to support the enryption explained later.
+\item mailsite - Alice's mailsite URI
+\end{itemize}
+
+Following the last data item, there are two carriage-return-line-feeds, followed by Alice's signature. This is the SHA-256 hash of the message RSA encrypted with Alice's private key, included as raw bytes. The resulting message is then RSA encrypted with Bob's public key. If the resulting message is longer than a single RSA block, the message is encoded in chunks equal to the maximum block size and the ciphertext blocks are concatenated to form the final message.
+
+The 'to' field is included to prevent surreptitious forwarding. That is, to prevent Bob from decrypting the message, leaving Alice's signature intact and encrypting it to someone else (say, Charlie), who would then be lead in to believing that Alice wished to communicate with him, which is fact not the case.
+
+This RTS message is then inserted to Freenet. The URI which it inserted to is derived from the 'rtskey' value in Bob's mailsite. The string, 'KSK@' is prepended a hyphen, the current date in the standard date format (see section \ref{standard_date}) is appended, followed by another hypen and a slot number. The slot number should be set to the lowest integer starting from 1, that does not cause a collision.
+
+\subsection{CTS Messages}
+
+\section{Message Exchange}
+\subsection{The Messages}
+
+\subsection{Message Acknowledgements}
+
+\appendix
+
+\section{Props Files}
+\label{PropsFile}
+A props file is a sequence of keys and values. Keys and values are separated by a single equals sign ('=') and lines are separated by a carrriage return and line feed ($\backslash$r$\backslash$n), with the exception that if the propsfile will only be read locally, it is permissable to use the line separator native to the local machine. For example, for props files that are never transmitted over the network, it is permissable to use just a line feed ($\backslash$n) to separate lines. It is recommended for simplicity, though not required, that the keys be lowercase and contain only alphanumeric characters. The keys must not contain the equals sign.
+
+An example of a propsfile is below: \\
+\\
+name=Bob Burton \\
+age=39 \\
+occupation=Builder \\
+Pet's Name=Stevie the Sycophantic Squirrel \\
+
+\section{Standard Date Format}
+\label{standard_date}
+A date in the standard format is the four digit year, two digit month and two digit day of the month. That is, "yyyyMMdd" in Java's SimpleDateFormat class notation. This is used to encode the day upon which and Freenet KSK key is inserted. For the purposes of considering when a key is inserted, this should be done accoring to Universal Standard Time, and not any local timezone or daylight saving time.
+
+\end{document}
From dbkr at freenetproject.org Tue Jul 11 19:42:19 2006
From: dbkr at freenetproject.org (Dave Baker)
Date: Tue, 11 Jul 2006 20:42:19 +0100
Subject: [Freemail] Status Update
Message-ID: <200607112042.20214.dbkr@freenetproject.org>
Hi all,
You may have just seen the first part of the specification document being
committed to subversion. This comprises all the parts of Freemail that I've
written so far. Tomorrow, I hope to write the rest of the document detailing
the protocol for the parts I haven't yet written. You are welcome (and
encouraged) to look over it and send comments to this list. If you spot
typos, those with SVN access are of course welcome to correct them.
For those unfamiliar with LaTeX, 'latex spec.tex' twice (don't ask) will get
you a DVI file. I'd say I'll insert the finished DVI file / PDF into Freenet,
although being offline for a while all my peers bar one seem to have died, so
that might be easier said than done.
Speaking of which, my house-move is now over and done with, (although I still
don't have an Internet connection), so apologies for the recent silence, but
normal service will now be resumed, albeit with little or no IRC presence and
no permanent Freenet node.
Dave
From dbkr at freenetproject.org Wed Jul 12 15:53:33 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Wed, 12 Jul 2006 15:53:33 +0000 (UTC)
Subject: [Freemail] r9576 - trunk/apps/Freemail/docs/spec
Message-ID: <20060712155333.CADF49BE28@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-12 15:53:30 +0000 (Wed, 12 Jul 2006)
New Revision: 9576
Modified:
trunk/apps/Freemail/docs/spec/spec.tex
Log:
Modifications to the spec doc as suggested by Toad.
Modified: trunk/apps/Freemail/docs/spec/spec.tex
===================================================================
--- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-12 14:41:05 UTC (rev 9575)
+++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-12 15:53:30 UTC (rev 9576)
@@ -8,7 +8,7 @@
\section{Introduction}
\subsection{What is Freemail}
-Freemail is an email-like messaging system that transports all messages over Freenet 0.7 in order to achieve anoymity and cencorship-resillience. Its protocol is designed to be as resistant as possible to attacks such as message floods and denial of service.
+Freemail is an email-like messaging system that transports all messages over Freenet 0.7 in order to achieve anonymity and cencorship-resillience. Its protocol is designed to be as resistant as possible to attacks such as message floods and denial of service. Unlike traditional email, it makes it extremely difficult for others to doscover what you have been communicating, who you have been communicating with, and even that you have been communicating at all.
Freemail uses IMAP and SMTP to interface with standard email clients, making taking advantage of interfaces that people are already accustomed to.
@@ -32,7 +32,7 @@
The following pieces of information are required in a mailpage:
\begin{itemize}
-\item rtskey - This is an arbitrary string of alphanumeric characters which is used to derive a KSK that can be used to send messages to the owner of the mailsite.
+\item rtskey - This is an arbitrary string of alphanumeric characters which is used to derive a KSK that can be used to send data to the owner of the mailsite in order to establish a communication channel.
\item asymkey.modulus - The modulus of the owner's RSA encryption key, as an integer in base 10.
\item asymkey.pubexponent - The public exponent of the owner's RSA encruption key, as an integer in base 10.
\end{itemize}
@@ -64,7 +64,7 @@
\section{Props Files}
\label{PropsFile}
-A props file is a sequence of keys and values. Keys and values are separated by a single equals sign ('=') and lines are separated by a carrriage return and line feed ($\backslash$r$\backslash$n), with the exception that if the propsfile will only be read locally, it is permissable to use the line separator native to the local machine. For example, for props files that are never transmitted over the network, it is permissable to use just a line feed ($\backslash$n) to separate lines. It is recommended for simplicity, though not required, that the keys be lowercase and contain only alphanumeric characters. The keys must not contain the equals sign.
+A props file is a sequence of keys and values. Keys and values are separated by a single equals sign ('=') and lines are separated by a carrriage return and line feed ($\backslash$r$\backslash$n), with the exception that if the propsfile will only be read locally, it is permissable to use the line separator native to the local machine. For example, for props files that are never transmitted over the network, it is permissable to use just a line feed ($\backslash$n) to separate lines. It is recommended for simplicity, though not required, that the keys be lowercase and contain only alphanumeric characters. The keys must not contain the equals sign, as there is no mechanism for escaping equals signs. The value may contain equals signs and therefore parsers of this format must treat and equals signs after the first on any line as part of the value text.
An example of a propsfile is below: \\
\\
From dbkr at freenetproject.org Wed Jul 12 16:01:20 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Wed, 12 Jul 2006 16:01:20 +0000 (UTC)
Subject: [Freemail] r9577 - trunk/apps/Freemail/docs/spec
Message-ID: <20060712160120.62DCA9BE28@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-12 16:01:17 +0000 (Wed, 12 Jul 2006)
New Revision: 9577
Modified:
trunk/apps/Freemail/docs/spec/spec.tex
Log:
Another spec correction
Modified: trunk/apps/Freemail/docs/spec/spec.tex
===================================================================
--- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-12 15:53:30 UTC (rev 9576)
+++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-12 16:01:17 UTC (rev 9577)
@@ -18,7 +18,7 @@
All Freemail users have an Freemail address, which one may give out to others in order to allow them to contact you. From this Freemail address, it is possible to derive a Freenet SSK URI. This is the user's 'mailsite'.
-A Freemail address comprises an arbitrary text string, followed by an '@' character. Following this is the mailsite address encoded in base 32 - that is, a valid Freenet uri that points to the mailsite. The string '.freenet' is appended to the whole address. An example Freemail address follows:
+A Freemail address comprises an arbitrary text string, followed by an '@' character. Following this is the mailsite address encoded in base 32 - that is, a valid Freenet uri that points to the mailsite. The URI must be base 32 encoded in order to make the address case insensitive to maintain compatability with traditional email clients. The string '.freenet' is appended to the whole address. An example Freemail address follows:
bob at KVJUWQCMJ53UI6KEGJKFI2JQIZZFKY3XG4YE4QRSMUYWYV2PLJ4U27TLGR4DI3TLNZXW6QTSJIYCYNKSOR4XK23MGZDS2UDRKVCTITBXJJWDQYKIOFMWC33VONTFOZTQMJZTS5LCONEWGY3WGQWECUKBIJAUCRJPNVQWS3DTNF2GKLZNGEXQ.freemail
From toad at amphibian.dyndns.org Wed Jul 12 16:52:18 2006
From: toad at amphibian.dyndns.org (Matthew Toseland)
Date: Wed, 12 Jul 2006 17:52:18 +0100
Subject: [Freemail] r9577 - trunk/apps/Freemail/docs/spec
In-Reply-To: <20060712160120.62DCA9BE28@emu.freenetproject.org>
References: <20060712160120.62DCA9BE28@emu.freenetproject.org>
Message-ID: <20060712165218.GE6187@amphibian.dyndns.org>
Cool, but wouldn't it be shorter than that? An example address:
USK at PFeLTa1si2Ml5sDeUy7eDhPso6TPdmw-2gWfQ4Jg02w,3ocfrqgUMVWA2PeorZx40TW0c-FiIOL-TWKQHoDbVdE,AQABAAE/Index/35/
(110)
We can drop the bits at each end:
PFeLTa1si2Ml5sDeUy7eDhPso6TPdmw-2gWfQ4Jg02w,3ocfrqgUMVWA2PeorZx40TW0c-FiIOL-TWKQHoDbVdE,AQABAAE (96)
And the commas:
PFeLTa1si2Ml5sDeUy7eDhPso6TPdmw-2gWfQ4Jg02w3ocfrqgUMVWA2PeorZx40TW0c-FiIOL-TWKQHoDbVdEAQABAAE (94)
But we have to use base32 instead of base64... that increases it to
94*6/5=113 chars... :<
Oh well.
On Wed, Jul 12, 2006 at 04:01:20PM +0000, dbkr at freenetproject.org wrote:
> Author: dbkr
> Date: 2006-07-12 16:01:17 +0000 (Wed, 12 Jul 2006)
> New Revision: 9577
>
> Modified:
> trunk/apps/Freemail/docs/spec/spec.tex
> Log:
> Another spec correction
>
>
> Modified: trunk/apps/Freemail/docs/spec/spec.tex
> ===================================================================
> --- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-12 15:53:30 UTC (rev 9576)
> +++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-12 16:01:17 UTC (rev 9577)
> @@ -18,7 +18,7 @@
>
> All Freemail users have an Freemail address, which one may give out to others in order to allow them to contact you. From this Freemail address, it is possible to derive a Freenet SSK URI. This is the user's 'mailsite'.
>
> -A Freemail address comprises an arbitrary text string, followed by an '@' character. Following this is the mailsite address encoded in base 32 - that is, a valid Freenet uri that points to the mailsite. The string '.freenet' is appended to the whole address. An example Freemail address follows:
> +A Freemail address comprises an arbitrary text string, followed by an '@' character. Following this is the mailsite address encoded in base 32 - that is, a valid Freenet uri that points to the mailsite. The URI must be base 32 encoded in order to make the address case insensitive to maintain compatability with traditional email clients. The string '.freenet' is appended to the whole address. An example Freemail address follows:
>
> bob at KVJUWQCMJ53UI6KEGJKFI2JQIZZFKY3XG4YE4QRSMUYWYV2PLJ4U27TLGR4DI3TLNZXW6QTSJIYCYNKSOR4XK23MGZDS2UDRKVCTITBXJJWDQYKIOFMWC33VONTFOZTQMJZTS5LCONEWGY3WGQWECUKBIJAUCRJPNVQWS3DTNF2GKLZNGEXQ.freemail
>
>
> _______________________________________________
> Freemail mailing list
> Freemail at freenetproject.org
> http://emu.freenetproject.org/cgi-bin/mailman/listinfo/freemail
>
--
Matthew J Toseland - toad at amphibian.dyndns.org
Freenet Project Official Codemonkey - http://freenetproject.org/
ICTHUS - Nothing is impossible. Our Boss says so.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://emu.freenetproject.org/pipermail/freemail/attachments/20060712/3045e3f8/attachment.pgp
From dbkr at freenetproject.org Wed Jul 12 17:29:30 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Wed, 12 Jul 2006 17:29:30 +0000 (UTC)
Subject: [Freemail] r9580 - trunk/apps/Freemail/docs/spec
Message-ID: <20060712172930.583239BCC4@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-12 17:29:28 +0000 (Wed, 12 Jul 2006)
New Revision: 9580
Modified:
trunk/apps/Freemail/docs/spec/spec.tex
Log:
More work on spec doc.
Modified: trunk/apps/Freemail/docs/spec/spec.tex
===================================================================
--- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-12 17:09:01 UTC (rev 9579)
+++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-12 17:29:28 UTC (rev 9580)
@@ -45,6 +45,7 @@
\item messagetype - This should be 'rts', to indicate that this message is an RTS.
\item to - The Freenet URI that appears encoded in Bob's Freemail address. This is necessary in order to prevent surreptitious forwarding to support the enryption explained later.
\item mailsite - Alice's mailsite URI
+\item ctsssk - A randomly generated KSK that Bob should insert to once he has recieved Alice's RTS message in order to acknoweldge that he is ready to recieve messages. This should be randomly generated and un-guessable so that only Bob knows which key to insert to.
\end{itemize}
Following the last data item, there are two carriage-return-line-feeds, followed by Alice's signature. This is the SHA-256 hash of the message RSA encrypted with Alice's private key, included as raw bytes. The resulting message is then RSA encrypted with Bob's public key. If the resulting message is longer than a single RSA block, the message is encoded in chunks equal to the maximum block size and the ciphertext blocks are concatenated to form the final message.
@@ -53,8 +54,23 @@
This RTS message is then inserted to Freenet. The URI which it inserted to is derived from the 'rtskey' value in Bob's mailsite. The string, 'KSK@' is prepended a hyphen, the current date in the standard date format (see section \ref{standard_date}) is appended, followed by another hypen and a slot number. The slot number should be set to the lowest integer starting from 1, that does not cause a collision.
+Alice then regularly polls the KSK she put as the value of 'ctsssk' until she retrives a CTS message (see next section).
+
\subsection{CTS Messages}
+When Bob recieves an RTS message from Alice, he decrypts the message using his RSA private key. He then retrives the mailsite advertised in the RTS message. Having done this, he reads the signature on the end and decrypts the signature with the public key he just retrieved from the mailsite. He then calculates a SHA-256 checksum of the message and checks that his checksum is identical to the one he has decrypted. If it is not, he must discard the message. This ensures that the message is really from Alice. He must then read the 'to' field and ensure that its value is identical to his mailsite URI. If it is not, he must discard the message. This ensures that he is the intended recipient of the message.
+Bob then records the value of the 'commssk' key so that he can poll this SSK for messages periodicaly. Before doing so, he creates another propfile with the following values:
+
+\begin{itemize}
+\item messagetype - This should be 'cts' to indicate that this is a clear-to-send message
+\end{itemize}
+
+Bob inserts this file to the value of the 'ctsssk' key in the RTS message.
+
+This message contains no valuable information and so does not need to be encrypted. It also does not need to be signed since only Alice and Bob know the KSK to which it must be inserted, so Alice knows that Bob must have inserted the message. The KSK that Bob inserts this message to tells Alice what RTS it relates to if there is any ambiguity.
+
+TODO: Polling of commssks.
+
\section{Message Exchange}
\subsection{The Messages}
From dbkr at freenetproject.org Sat Jul 15 18:14:54 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Sat, 15 Jul 2006 18:14:54 +0000 (UTC)
Subject: [Freemail] r9628 - trunk/apps/Freemail/docs/spec
Message-ID: <20060715181454.9C3F89BEB0@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-15 18:14:51 +0000 (Sat, 15 Jul 2006)
New Revision: 9628
Modified:
trunk/apps/Freemail/docs/spec/spec.tex
Log:
Finish off the spec doc (working draft anyway)
Modified: trunk/apps/Freemail/docs/spec/spec.tex
===================================================================
--- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-15 16:23:26 UTC (rev 9627)
+++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-15 18:14:51 UTC (rev 9628)
@@ -20,10 +20,11 @@
A Freemail address comprises an arbitrary text string, followed by an '@' character. Following this is the mailsite address encoded in base 32 - that is, a valid Freenet uri that points to the mailsite. The URI must be base 32 encoded in order to make the address case insensitive to maintain compatability with traditional email clients. The string '.freenet' is appended to the whole address. An example Freemail address follows:
-bob at KVJUWQCMJ53UI6KEGJKFI2JQIZZFKY3XG4YE4QRSMUYWYV2PLJ4U27TLGR4DI3TLNZXW6QTSJIYCYNKSOR4XK23MGZDS2UDRKVCTITBXJJWDQYKIOFMWC33VONTFOZTQMJZTS5LCONEWGY3WGQWECUKBIJAUCRJPNVQWS3DTNF2GKLZNGEXQ.freemail
+bob at KVJUWQCMJ53UI6KEGJKFI2JQIZZFKY3XG\-4YE4QRSMUYWYV2PLJ4U27TLG\-R4DI3TLNZXW6QTSJIYCYNKS\-OR4XK23MGZDS2UDRKVCTIT\-BXJJWDQYKIOFM\-WC33VONTFOZTQMJZTS5LCO\-NEWGY3WGQWECUKBIJA\-UCRJPNVQWS3DTNF\-2GKLZNGEXQ.freemail
-The base 32 encoded mailsite in this case is: USK at LOwDyD2TTi0FrUcw70NB2e1lWOZyM~k4x4nknooBrJ0,5Rtyukl6G-PqUE4L7Jl8aHqYaousfWfpbs9ubsIccv4,AQABAAE/mailsite/-1/
+The base 32 encoded mailsite in this case is: USK at LOwDyD2TTi0FrUcw70N\-B2e1lWOZyM~k4x4n\-knooBrJ0,5Rtyu\-kl6G-PqUE4L7\-Jl8aHqYaous\-fWfpbs9ubsI\-ccv4,AQABAAE/mailsite/-1/
+
(this is liable to change to make the addresses shorter)
Once the mailsite address has been obtained from the Freemail address, the string 'mailpage' is appended to obtain the URI for the mailpage. This mailpage contains all information required to contact the owner. The format of a mailpage is a 'Props File', which is used repeatedly in Freemail as a trivial format for storing short pieces of information. See section \ref{PropsFile}.
@@ -41,7 +42,8 @@
Once Alice has retrieved the recipient's mailpage, she sends an RTS message to Bob. This RTS message is, again, a props file, with the following keys:
\begin{itemize}
-\item commssk - The SSK URI to which messages will be inserted.
+\item commssk - The public SSK URI to which messages will be inserted.
+\item ackssk - A fresh SSK private (insert) key that Bob will insert to in order to acknowledge his reciept of each message.
\item messagetype - This should be 'rts', to indicate that this message is an RTS.
\item to - The Freenet URI that appears encoded in Bob's Freemail address. This is necessary in order to prevent surreptitious forwarding to support the enryption explained later.
\item mailsite - Alice's mailsite URI
@@ -50,6 +52,8 @@
Following the last data item, there are two carriage-return-line-feeds, followed by Alice's signature. This is the SHA-256 hash of the message RSA encrypted with Alice's private key, included as raw bytes. The resulting message is then RSA encrypted with Bob's public key. If the resulting message is longer than a single RSA block, the message is encoded in chunks equal to the maximum block size and the ciphertext blocks are concatenated to form the final message.
+It is the sender's responsibility to keep the private part of the 'commssk' key private. It is valid to assume that any message inserted on 'commssk' was written by Alice and intended for Bob, since only Alice has the private key and only they have the public key.
+
The 'to' field is included to prevent surreptitious forwarding. That is, to prevent Bob from decrypting the message, leaving Alice's signature intact and encrypting it to someone else (say, Charlie), who would then be lead in to believing that Alice wished to communicate with him, which is fact not the case.
This RTS message is then inserted to Freenet. The URI which it inserted to is derived from the 'rtskey' value in Bob's mailsite. The string, 'KSK@' is prepended a hyphen, the current date in the standard date format (see section \ref{standard_date}) is appended, followed by another hypen and a slot number. The slot number should be set to the lowest integer starting from 1, that does not cause a collision.
@@ -65,17 +69,62 @@
\item messagetype - This should be 'cts' to indicate that this is a clear-to-send message
\end{itemize}
-Bob inserts this file to the value of the 'ctsssk' key in the RTS message.
+Bob inserts this file to the value of the 'ctsssk' key in the RTS message. This completes Bob's part of the channel setup procedure.
This message contains no valuable information and so does not need to be encrypted. It also does not need to be signed since only Alice and Bob know the KSK to which it must be inserted, so Alice knows that Bob must have inserted the message. The KSK that Bob inserts this message to tells Alice what RTS it relates to if there is any ambiguity.
-TODO: Polling of commssks.
+Alice should check periodically for the insertion of this CTS message. If it does not arrive, Alice should re-send the RTS message with a different 'ctsssk', in order that she can be certain which RRS message any given CTS message corresponds to. All other field should be the same. The client may try several times before declaring the message undeliverable.
\section{Message Exchange}
\subsection{The Messages}
+Once Bob has inserted this CTS message, he begins polling for messages on keys derived from the value of the 'commssk' key which he obtained from the RTS message. These keys are the value of 'comssk' with the string 'message-' and a natural number appended, where the number is the lowest number that does not form a key on which Bob has already received a message (the 'lowest free slot'). For example:
+SSK at 9GXtGxN4CEJD~8a30\-7V6yzyhl8Gx5UYb\-WVDTEyUXH6o,gDWfr2CqVmDAeJ\-urKF2iieM5AkjXs\-tOl2V5jyuTHeo4,AQABAAE/message-1
+
+Once Bob has successfully retrived this key, he begins to periodically request the key:
+
+SSK at 9GXtGxN4CEJD~8a30\-7V6yzyhl8Gx5UYbW\-VDTEyUXH6o,gDWfr2CqVmDAeJ\-urKF2iieM5AkjXs\-tOl2V5jyuTHeo4,AQABAAE/message-2
+
+It is recommended that clients poll several messages ahead rather than just the immediately next message, since simulations suggest that it is possible for single keys not to be retrivable in this kind of circumstance. So for example, once Bob has sent his CTS messages, he should start polling for the keys:
+
+number that does not form a key on which Bob has already received a message (the 'lowest free slot'). For example: \\
+\\
+SSK at 9GXtGxN4CEJD~8a\-307V6yzyhl8Gx5U\-YbWVDTEyUXH6o,gDWfr2CqVm\-DAeJurKF2iieM\-5AkjXstOl2V5j\-yuTHeo4,AQABAAE/message-1 \\
+\\
+SSK at 9GXtGxN4CEJD~8a\-307V6yzyhl8Gx5U\-YbWVDTEyUXH6o,gDWfr2CqVm\-DAeJurKF2iieM\-5AkjXstOl2V5j\-yuTHeo4,AQABAAE/message-2 \\
+\\
+and \\
+SSK at 9GXtGxN4CEJD~8a\-307V6yzyhl8Gx5U\-YbWVDTEyUXH6o,gDWfr2CqVm\-DAeJurKF2iieM\-5AkjXstOl2V5j\-yuTHeo4,AQABAAE/message-3
+
+Alice can insert a message to the lowest numbered key of this pattern that does not cause a collision whenever she chooses. These comprise a number of properties (in the same way as a props file) followed by a double carriage-return-line-feed. Following this is the standard MIME mail messages. No signing or encryption is used here, since at this stage it is achieved inside Freenet by virtue of only Alice and Bob knowing the SSK upon which they communicate.
+
+The only mandatory property is 'id' which may be any integer, but must uniquely identify the message from any other past or future message transported using the same 'commssk'. Bob must check this value and ensure that he has not already recieved this message id. If he has, he discards the message, but still ackowledges his reciept of it. All clients must ignore any unknown keys and begin reading the message only at the double line break in order that extra properties can be added in the future.
+
\subsection{Message Acknowledgements}
+When Bob recieves a message on the 'commssk', he reads it and passes it onto the user. He then inserts some data to the key 'ackssk' (which he obtains from the original RTS message) with 'ack-' and the value of 'id' from the message in question. For example, if Bob has just fetched a message from key: \\
+\\
+SSK at 9GXtGxN4CEJD~8a\-307V6yzyhl8Gx5U\-YbWVDTEyUXH6o,gDWfr2CqVm\-DAeJurKF2iieM\-5AkjXstOl2V5j\-yuTHeo4,AQABAAE/message-1 \\
+\\
+With the contents: \\
+\\
+\fbox{\begin{minipage}[h]{400pt}
+id=657488664753 \\
+
+To: Bob Burton $<$bob at longkey.freemail$>$ \\
+From: Alice Andrews $<$alice at anotherlongkey.freemail$>$ \\
+Subject: Eve \\
+
+I think Eve from down the road might be trying to spy on us. I've never liked the looked of her, you know. It's always the quiet ones.
+\end{minipage}} \\
+\\
+Then he might insert an acknowledgement to the key: \\
+\\
+\\
+SSK at AJoZbUvGkXlAJwI\-jdbu9BLPhpIXBu6\-w6nGwKYBnMfNLi,ACEgE1uUIzJdC\-Xcsz1yjgW45u\-Az-KuMrXBFYG\-U8maqc/ack-1 \\
+\\
+The data that Bob publishes to this key is irrelevant - its mere existance in the network is sufficient to assert Bob's reciept of the message.
+
\appendix
\section{Props Files}
@@ -84,10 +133,12 @@
An example of a propsfile is below: \\
\\
+\fbox{\begin{minipage}{400pt}
name=Bob Burton \\
age=39 \\
occupation=Builder \\
Pet's Name=Stevie the Sycophantic Squirrel \\
+\end{minipage}}
\section{Standard Date Format}
\label{standard_date}
From dbkr at freenetproject.org Sun Jul 16 17:35:40 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Sun, 16 Jul 2006 17:35:40 +0000 (UTC)
Subject: [Freemail] r9634 - in trunk/apps/Freemail: . src/freemail
src/freemail/utils
Message-ID: <20060716173540.C0E9D9BC35@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-16 17:35:37 +0000 (Sun, 16 Jul 2006)
New Revision: 9634
Added:
trunk/apps/Freemail/src/freemail/NIMFetcher.java
trunk/apps/Freemail/src/freemail/RTSFetcher.java
Removed:
trunk/apps/Freemail/src/freemail/MailFetcher.java
Modified:
trunk/apps/Freemail/build.xml
trunk/apps/Freemail/src/freemail/AccountManager.java
trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
trunk/apps/Freemail/src/freemail/utils/PropsFile.java
Log:
Poll for RTS messages
Modified: trunk/apps/Freemail/build.xml
===================================================================
--- trunk/apps/Freemail/build.xml 2006-07-16 17:30:25 UTC (rev 9633)
+++ trunk/apps/Freemail/build.xml 2006-07-16 17:35:37 UTC (rev 9634)
@@ -24,7 +24,7 @@
-
+
Modified: trunk/apps/Freemail/src/freemail/AccountManager.java
===================================================================
--- trunk/apps/Freemail/src/freemail/AccountManager.java 2006-07-16 17:30:25 UTC (rev 9633)
+++ trunk/apps/Freemail/src/freemail/AccountManager.java 2006-07-16 17:35:37 UTC (rev 9634)
@@ -58,12 +58,7 @@
if (!contacts_dir.mkdir()) throw new IOException("Failed to create contacts directory");
}
- File inbound_dir = new File(contacts_dir, SingleAccountWatcher.INBOUND_DIR);
- if (!inbound_dir.exists()) {
- if (!inbound_dir.mkdir()) throw new IOException("Failed to create inbound contacts directory");
- }
-
- File nimdir = new File(inbound_dir, NIMDIR);
+ File nimdir = new File(contacts_dir, NIMDIR);
if (!nimdir.exists()) {
if (!nimdir.mkdir()) throw new IOException("Failed to create nim directory");
}
Deleted: trunk/apps/Freemail/src/freemail/MailFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/MailFetcher.java 2006-07-16 17:30:25 UTC (rev 9633)
+++ trunk/apps/Freemail/src/freemail/MailFetcher.java 2006-07-16 17:35:37 UTC (rev 9634)
@@ -1,134 +0,0 @@
-package freemail;
-
-import freemail.fcp.FCPConnection;
-import freemail.fcp.HighLevelFCPClient;
-import freemail.utils.DateStringFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.BufferedReader;
-import java.io.PrintStream;
-import java.io.FileReader;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Calendar;
-import java.util.TimeZone;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import org.bouncycastle.util.encoders.Hex;
-
-public class MailFetcher {
- private final MessageBank mb;
- private File contact_dir;
- private final FCPConnection fcpconn;
- private final SimpleDateFormat sdf;
- private static final int POLL_AHEAD = 3;
- private static int PASSES_PER_DAY = 3;
- private static int MAX_DAYS_BACK = 30;
-
- MailFetcher(MessageBank m, File ctdir, FCPConnection fcpc) {
- this.mb = m;
- this.fcpconn = fcpc;
- this.sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z");
- this.contact_dir = ctdir;
- }
-
- public void fetch_from_all() {
- File[] contactfiles = contact_dir.listFiles();
-
- for (int i = 0; i < contactfiles.length; i++) {
- Contact contact = new Contact(contactfiles[i]);
- this.fetch_from(contact);
- }
- }
-
- private void fetch_from(Contact contact) {
- int i;
- for (i = 1 - MAX_DAYS_BACK; i <= 0; i++) {
- String datestr = DateStringFactory.getOffsetKeyString(i);
- MailLog log = contact.getLog(datestr);
-
- if (log.getPasses() < PASSES_PER_DAY) {
- this.fetch_day(contact, log, datestr);
- // don't count passes for today since more
- // mail may arrive
- if (i < 0) log.incPasses();
- }
- }
-
- TimeZone gmt = TimeZone.getTimeZone("GMT");
- Calendar cal = Calendar.getInstance(gmt);
- cal.setTime(new Date());
-
- cal.add(Calendar.DAY_OF_MONTH, 0 - MAX_DAYS_BACK);
- contact.pruneLogs(cal.getTime());
- }
-
- public void fetch_day(Contact contact, MailLog log, String date) {
- HighLevelFCPClient fcpcli;
- fcpcli = new HighLevelFCPClient();
-
- String keybase;
- try {
- keybase = contact.getKey() + date + "-";
- } catch (IOException ioe) {
- // Jinkies, Scoob! No key!
- return;
- }
-
- int startnum = log.getNextMessageId();
-
- for (int i = startnum; i < startnum + POLL_AHEAD; i++) {
- System.out.println("trying to fetch "+keybase+i);
-
- File result = fcpcli.fetch(keybase+i);
-
- if (result != null) {
- System.out.println(keybase+i+": got message!");
- try {
- String checksum = this.storeMessage(result);
- log.addMessage(i, checksum);
- } catch (IOException ioe) {
- continue;
- }
- } else {
- System.out.println(keybase+i+": no message.");
- }
- }
- }
-
- private String storeMessage(File file) throws IOException {
- MailMessage newmsg = this.mb.createMessage();
-
- MessageDigest md;
- try {
- md = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException alge) {
- System.out.println("No MD5 implementation available - can't checksum messages - not storing message.");
- return null;
- }
-
- // add our own headers first
- // recieved and date
- newmsg.addHeader("Received", "(Freemail); "+this.sdf.format(new Date()));
-
- BufferedReader rdr = new BufferedReader(new FileReader(file));
-
- newmsg.readHeaders(rdr);
-
- PrintStream ps = newmsg.writeHeadersAndGetStream();
-
- String line;
- while ( (line = rdr.readLine()) != null) {
- ps.println(line);
- }
-
- newmsg.commit();
- rdr.close();
- file.delete();
-
- byte[] checksum = md.digest();
- return new String(Hex.encode(checksum));
- }
-}
Copied: trunk/apps/Freemail/src/freemail/NIMFetcher.java (from rev 9629, trunk/apps/Freemail/src/freemail/MailFetcher.java)
===================================================================
--- trunk/apps/Freemail/src/freemail/MailFetcher.java 2006-07-15 21:40:40 UTC (rev 9629)
+++ trunk/apps/Freemail/src/freemail/NIMFetcher.java 2006-07-16 17:35:37 UTC (rev 9634)
@@ -0,0 +1,125 @@
+package freemail;
+
+import freemail.fcp.FCPConnection;
+import freemail.fcp.HighLevelFCPClient;
+import freemail.utils.DateStringFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.PrintStream;
+import java.io.FileReader;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.bouncycastle.util.encoders.Hex;
+
+public class NIMFetcher {
+ private final MessageBank mb;
+ private File contact_dir;
+ private final SimpleDateFormat sdf;
+ private static final int POLL_AHEAD = 3;
+ private static int PASSES_PER_DAY = 3;
+ private static int MAX_DAYS_BACK = 30;
+
+ NIMFetcher(MessageBank m, File ctdir) {
+ this.mb = m;
+ this.sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z");
+ this.contact_dir = ctdir;
+ }
+
+ public void fetch() {
+ Contact contact = new Contact(this.contact_dir);
+
+ int i;
+ for (i = 1 - MAX_DAYS_BACK; i <= 0; i++) {
+ String datestr = DateStringFactory.getOffsetKeyString(i);
+ MailLog log = contact.getLog(datestr);
+
+ if (log.getPasses() < PASSES_PER_DAY) {
+ this.fetch_day(contact, log, datestr);
+ // don't count passes for today since more
+ // mail may arrive
+ if (i < 0) log.incPasses();
+ }
+ }
+
+ TimeZone gmt = TimeZone.getTimeZone("GMT");
+ Calendar cal = Calendar.getInstance(gmt);
+ cal.setTime(new Date());
+
+ cal.add(Calendar.DAY_OF_MONTH, 0 - MAX_DAYS_BACK);
+ contact.pruneLogs(cal.getTime());
+ }
+
+ private void fetch_day(Contact contact, MailLog log, String date) {
+ HighLevelFCPClient fcpcli;
+ fcpcli = new HighLevelFCPClient();
+
+ String keybase;
+ try {
+ keybase = contact.getKey() + date + "-";
+ } catch (IOException ioe) {
+ // Jinkies, Scoob! No key!
+ return;
+ }
+
+ int startnum = log.getNextMessageId();
+
+ for (int i = startnum; i < startnum + POLL_AHEAD; i++) {
+ System.out.println("trying to fetch "+keybase+i);
+
+ File result = fcpcli.fetch(keybase+i);
+
+ if (result != null) {
+ System.out.println(keybase+i+": got message!");
+ try {
+ String checksum = this.storeMessage(result);
+ log.addMessage(i, checksum);
+ } catch (IOException ioe) {
+ continue;
+ }
+ } else {
+ System.out.println(keybase+i+": no message.");
+ }
+ }
+ }
+
+ private String storeMessage(File file) throws IOException {
+ MailMessage newmsg = this.mb.createMessage();
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException alge) {
+ System.out.println("No MD5 implementation available - can't checksum messages - not storing message.");
+ return null;
+ }
+
+ // add our own headers first
+ // recieved and date
+ newmsg.addHeader("Received", "(Freemail); "+this.sdf.format(new Date()));
+
+ BufferedReader rdr = new BufferedReader(new FileReader(file));
+
+ newmsg.readHeaders(rdr);
+
+ PrintStream ps = newmsg.writeHeadersAndGetStream();
+
+ String line;
+ while ( (line = rdr.readLine()) != null) {
+ ps.println(line);
+ }
+
+ newmsg.commit();
+ rdr.close();
+ file.delete();
+
+ byte[] checksum = md.digest();
+ return new String(Hex.encode(checksum));
+ }
+}
Copied: trunk/apps/Freemail/src/freemail/RTSFetcher.java (from rev 9629, trunk/apps/Freemail/src/freemail/MailFetcher.java)
===================================================================
--- trunk/apps/Freemail/src/freemail/MailFetcher.java 2006-07-15 21:40:40 UTC (rev 9629)
+++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-16 17:35:37 UTC (rev 9634)
@@ -0,0 +1,82 @@
+package freemail;
+
+import freemail.fcp.FCPConnection;
+import freemail.fcp.HighLevelFCPClient;
+import freemail.utils.DateStringFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.PrintStream;
+import java.io.FileReader;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.bouncycastle.util.encoders.Hex;
+
+public class RTSFetcher {
+ private String rtskey;
+ private File contact_dir;
+ private final SimpleDateFormat sdf;
+ private static final int POLL_AHEAD = 3;
+ private static int PASSES_PER_DAY = 3;
+ private static int MAX_DAYS_BACK = 30;
+ private static String LOGFILE = "rtslog";
+
+ RTSFetcher(String key, File ctdir) {
+ this.rtskey = key;
+ this.sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z");
+ this.contact_dir = ctdir;
+ }
+
+ public void fetch() {
+ int i;
+ RTSLog log = new RTSLog(new File(this.contact_dir, LOGFILE));
+ for (i = 1 - MAX_DAYS_BACK; i <= 0; i++) {
+ String datestr = DateStringFactory.getOffsetKeyString(i);
+ if (log.getPasses(datestr) < PASSES_PER_DAY) {
+ this.fetch_day(log, datestr);
+ // don't count passes for today since more
+ // mail may arrive
+ if (i < 0) {
+ log.incPasses(datestr);
+ }
+ }
+ }
+
+ TimeZone gmt = TimeZone.getTimeZone("GMT");
+ Calendar cal = Calendar.getInstance(gmt);
+ cal.setTime(new Date());
+
+ cal.add(Calendar.DAY_OF_MONTH, 0 - MAX_DAYS_BACK);
+ log.pruneBefore(cal.getTime());
+ }
+
+ private void fetch_day(RTSLog log, String date) {
+ HighLevelFCPClient fcpcli;
+ fcpcli = new HighLevelFCPClient();
+
+ String keybase;
+ keybase = this.rtskey + date + "-";
+
+ int startnum = log.getNextId(date);
+
+ for (int i = startnum; i < startnum + POLL_AHEAD; i++) {
+ System.out.println("trying to fetch "+keybase+i);
+
+ File result = fcpcli.fetch(keybase+i);
+
+ if (result != null) {
+ System.out.println(keybase+i+": got RTS!");
+ log.incNextId(date);
+ // TODO: handle the RTS!
+ } else {
+ System.out.println(keybase+i+": no RTS.");
+ }
+ }
+ }
+}
Modified: trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-16 17:30:25 UTC (rev 9633)
+++ trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-16 17:35:37 UTC (rev 9634)
@@ -11,27 +11,48 @@
private static final int MIN_POLL_DURATION = 60000; // in milliseconds
private static final int MAILSITE_UPLOAD_INTERVAL = 60 * 60 * 1000;
private final MessageBank mb;
- private final MailFetcher mf;
+ private final NIMFetcher nf;
+ private final RTSFetcher rtsf;
SingleAccountWatcher(File accdir) {
File contacts_dir = new File(accdir, CONTACTS_DIR);
File inbound_dir = new File(contacts_dir, INBOUND_DIR);
+ if (!inbound_dir.exists()) {
+ inbound_dir.mkdir();
+ }
+
// TODO: do this in the loop, periodically
PropsFile accprops = AccountManager.getAccountFile(accdir);
MailSite ms = new MailSite(accprops);
ms.Publish();
this.mb = new MessageBank(accdir.getName());
- this.mf = new MailFetcher(this.mb, inbound_dir, Freemail.getFCPConnection());
+
+ File nimdir = new File(contacts_dir, AccountManager.NIMDIR);
+ if (nimdir.exists()) {
+ this.nf = new NIMFetcher(this.mb, nimdir);
+ } else {
+ this.nf = null;
+ }
+
+ this.rtsf = new RTSFetcher("KSK@"+accprops.get("rtskey")+"-", inbound_dir);
+
+ //this.mf = new MailFetcher(this.mb, inbound_dir, Freemail.getFCPConnection());
}
public void run() {
while (true) {
long start = System.currentTimeMillis();
- mf.fetch_from_all();
+ if (this.nf != null) {
+ nf.fetch();
+ }
+ this.rtsf.fetch();
+
+ //mf.fetch_from_all();
+
long runtime = System.currentTimeMillis() - start;
if (MIN_POLL_DURATION - runtime > 0) {
Modified: trunk/apps/Freemail/src/freemail/utils/PropsFile.java
===================================================================
--- trunk/apps/Freemail/src/freemail/utils/PropsFile.java 2006-07-16 17:30:25 UTC (rev 9633)
+++ trunk/apps/Freemail/src/freemail/utils/PropsFile.java 2006-07-16 17:35:37 UTC (rev 9634)
@@ -9,6 +9,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
public class PropsFile {
private final File file;
@@ -79,4 +80,12 @@
public boolean exists() {
return this.file.exists();
}
+
+ public Set listProps() {
+ return this.data.keySet();
+ }
+
+ public void remove(String key) {
+ this.data.remove(key);
+ }
}
From droden at gmail.com Mon Jul 17 05:39:48 2006
From: droden at gmail.com (David 'Bombe' Roden)
Date: Mon, 17 Jul 2006 07:39:48 +0200
Subject: [Freemail] r9634 - in trunk/apps/Freemail: . src/freemail
src/freemail/utils
In-Reply-To: <20060716173540.C0E9D9BC35@emu.freenetproject.org>
References: <20060716173540.C0E9D9BC35@emu.freenetproject.org>
Message-ID: <200607170739.57238.droden@gmail.com>
On Sunday 16 July 2006 19:35, dbkr at freenetproject.org wrote:
> trunk/apps/Freemail/src/freemail/RTSFetcher.java
RTSLog is missing. :)
David
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: not available
Url : http://emu.freenetproject.org/pipermail/freemail/attachments/20060717/5c693b33/attachment.pgp
From dbkr at freenetproject.org Mon Jul 17 11:31:09 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Mon, 17 Jul 2006 11:31:09 +0000 (UTC)
Subject: [Freemail] r9643 - trunk/apps/Freemail/src/freemail
Message-ID: <20060717113109.DD8B79BE31@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-17 11:31:07 +0000 (Mon, 17 Jul 2006)
New Revision: 9643
Added:
trunk/apps/Freemail/src/freemail/RTSLog.java
Log:
D'oh.
Added: trunk/apps/Freemail/src/freemail/RTSLog.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSLog.java 2006-07-17 07:56:31 UTC (rev 9642)
+++ trunk/apps/Freemail/src/freemail/RTSLog.java 2006-07-17 11:31:07 UTC (rev 9643)
@@ -0,0 +1,71 @@
+package freemail;
+
+import java.util.Date;
+import java.util.Set;
+import java.util.Iterator;
+import java.io.File;
+
+import freemail.utils.PropsFile;
+import freemail.utils.DateStringFactory;
+
+public class RTSLog {
+ PropsFile logfile;
+ private static String NEXTID = "nextid-";
+ private static String PASSES = "passes-";
+
+ public RTSLog(File f) {
+ this.logfile = new PropsFile(f);
+ }
+
+ public int getPasses(String day) {
+ String val = this.logfile.get(PASSES+day);
+
+ if (val == null)
+ return 0;
+ else
+ return Integer.parseInt(val);
+ }
+
+ public void incPasses(String day) {
+ this.logfile.put(PASSES+day, Integer.toString(this.getPasses(PASSES+day) + 1));
+ }
+
+ public void pruneBefore(Date keepafter) {
+ Set props = this.logfile.listProps();
+
+ Iterator i = props.iterator();
+ while (i.hasNext()) {
+ String cur = (String)i.next();
+
+ String datestr;
+ if (cur.startsWith(PASSES)) {
+ datestr = cur.substring(PASSES.length());
+ } else if (cur.startsWith(NEXTID)) {
+ datestr = cur.substring(NEXTID.length());
+ } else {
+ continue;
+ }
+
+ Date logdate = DateStringFactory.DateFromKeyString(datestr);
+ if (logdate == null) {
+ // couldn't parse the date... hmm
+ this.logfile.remove(cur);
+ } else if (logdate.before(keepafter)) {
+ this.logfile.remove(cur);
+ }
+ }
+ }
+
+ public int getNextId(String day) {
+ String nid = this.logfile.get(NEXTID+day);
+ if (nid == null) {
+ return 1;
+ } else {
+ return Integer.parseInt(nid);
+ }
+ }
+
+ public void incNextId(String day) {
+ this.logfile.put(NEXTID+day, Integer.toString(this.getNextId(day) + 1));
+ }
+}
From dbkr at freenetproject.org Mon Jul 17 17:01:41 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Mon, 17 Jul 2006 17:01:41 +0000 (UTC)
Subject: [Freemail] r9645 - in trunk/apps/Freemail/src/freemail: . utils
Message-ID: <20060717170141.B7D2E9C754@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-17 17:01:38 +0000 (Mon, 17 Jul 2006)
New Revision: 9645
Modified:
trunk/apps/Freemail/src/freemail/RTSFetcher.java
trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
trunk/apps/Freemail/src/freemail/utils/ChainedAsymmetricBlockCipher.java
Log:
Work on processing RTS messages. Not done yet.
Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-17 14:44:49 UTC (rev 9644)
+++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-17 17:01:38 UTC (rev 9645)
@@ -3,8 +3,13 @@
import freemail.fcp.FCPConnection;
import freemail.fcp.HighLevelFCPClient;
import freemail.utils.DateStringFactory;
+import freemail.utils.PropsFile;
+import freemail.utils.ChainedAsymmetricBlockCipher;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.PrintStream;
@@ -17,7 +22,13 @@
import java.security.NoSuchAlgorithmException;
import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.crypto.AsymmetricBlockCipher;
+import org.bouncycastle.crypto.engines.RSAEngine;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import freenet.support.io.LineReadingInputStream;
+
public class RTSFetcher {
private String rtskey;
private File contact_dir;
@@ -26,11 +37,16 @@
private static int PASSES_PER_DAY = 3;
private static int MAX_DAYS_BACK = 30;
private static String LOGFILE = "rtslog";
+ private static int RTS_MAX_SIZE = 2 * 1024 * 1024;
+ private File accdir;
+ private PropsFile accprops;
- RTSFetcher(String key, File ctdir) {
+ RTSFetcher(String key, File ctdir, File ad) {
this.rtskey = key;
this.sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z");
this.contact_dir = ctdir;
+ this.accdir = ad;
+ this.accprops = AccountManager.getAccountFile(this.accdir);
}
public void fetch() {
@@ -72,11 +88,164 @@
if (result != null) {
System.out.println(keybase+i+": got RTS!");
- log.incNextId(date);
- // TODO: handle the RTS!
+ // if we didn't successfully handle (or fatally fail to handle) the RTS message, don't increment the id, so we'll get it again in a bit
+ if (this.handle_rts(result)) {
+ log.incNextId(date);
+ }
+ result.delete();
} else {
System.out.println(keybase+i+": no RTS.");
}
}
}
+
+
+
+ private boolean handle_rts(File rtsmessage) {
+ // sanity check!
+ if (!rtsmessage.exists()) return false;
+
+ if (rtsmessage.length() > RTS_MAX_SIZE) {
+ System.out.println("RTS Message is too large - discarding!");
+ return true;
+ }
+
+ // decrypt
+ byte[] plaintext;
+ try {
+ plaintext = decrypt_rts(rtsmessage);
+ } catch (IOException ioe) {
+ System.out.println("Error reading RTS message!");
+ return false;
+ } catch (InvalidCipherTextException icte) {
+ System.out.println("Could not decrypt RTS message - discarding.");
+ return true;
+ }
+
+ File rtsfile;
+ byte[] sig;
+ int messagebytes = 0;
+ try {
+ rtsfile = File.createTempFile("rtstmp", "tmp", Freemail.getTempDir());
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(plaintext);
+ LineReadingInputStream lis = new LineReadingInputStream(bis);
+ PrintStream ps = new PrintStream(new FileOutputStream(rtsfile));
+
+ String line;
+ while (true) {
+ line = lis.readLine(200, 200);
+ messagebytes += lis.getLastBytesRead();
+
+ if (line == null || line.equals("")) break;
+
+ ps.println(line);
+ }
+
+ ps.close();
+
+ if (line == null) {
+ // that's not right, we shouldn't have reached the end of the file, just the blank line before the signature
+
+ System.out.println("Couldn't find signature on RTS message - ignoring!");
+ return true;
+ }
+
+ sig = new byte[bis.available()];
+
+ int read = 0;
+ while (true) {
+ read = bis.read(sig, 0, bis.available());
+ if (read == 0) break;
+ }
+ bis.close();
+ } catch (IOException ioe) {
+ System.out.println("IO error whilst handling RTS message. "+ioe.getMessage());
+ ioe.printStackTrace();
+ return false;
+ }
+
+ PropsFile rtsprops = new PropsFile(rtsfile);
+
+ try {
+ validate_rts(rtsprops);
+ } catch (Exception e) {
+ System.out.println("RTS message does not contain vital information: "+e.getMessage()+" - discarding");
+ return true;
+ }
+
+ // verify the signature
+ String their_mailsite = rtsprops.get("mailsite");
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException alge) {
+ System.out.println("No MD5 implementation available - sorry, Freemail cannot work!");
+ return false;
+ }
+ md.update(plaintext, 0, messagebytes);
+ byte[] our_hash = md.digest();
+
+ HighLevelFCPClient fcpcli = new HighLevelFCPClient();
+ fcpcli.fetch(their_mailsite);
+
+ // TODO: finish.
+
+ // verify the message is for us
+
+ // create the inbound contact
+
+ // move the props file to the right place
+
+ return true;
+ }
+
+ private byte[] decrypt_rts(File rtsmessage) throws IOException, InvalidCipherTextException {
+ byte[] ciphertext = new byte[(int)rtsmessage.length()];
+ FileInputStream fis = new FileInputStream(rtsmessage);
+ int read = 0;
+ while (read < rtsmessage.length()) {
+ read += fis.read(ciphertext, read, (int)rtsmessage.length() - read);
+ }
+
+ RSAKeyParameters ourprivkey = AccountManager.getPrivateKey(this.accdir);
+
+ // decrypt it
+ AsymmetricBlockCipher deccipher = new RSAEngine();
+ deccipher.init(false, ourprivkey);
+ byte[] plaintext = ChainedAsymmetricBlockCipher.decrypt(deccipher, ciphertext);
+
+ return plaintext;
+ }
+
+ /*
+ * Make sure an RTS file has all the right properties in it
+ * If any are missing, throw an exception which says which are missing
+ */
+ private void validate_rts(PropsFile rts) throws Exception {
+ StringBuffer missing = new StringBuffer();
+
+ if (rts.get("commssk") == null) {
+ missing.append("commssk");
+ }
+ if (rts.get("ackssk") == null) {
+ missing.append("ackssk");
+ }
+ if (rts.get("messagetype") == null) {
+ missing.append("messagetype");
+ }
+ if (rts.get("to") == null) {
+ missing.append("to");
+ }
+ if (rts.get("mailsite") == null) {
+ missing.append("mailsite");
+ }
+ if (rts.get("ctsssk") == null) {
+ missing.append("ctsssk");
+ }
+
+ if (missing.length() == 0) return;
+ throw new Exception(missing.toString());
+ }
}
Modified: trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-17 14:44:49 UTC (rev 9644)
+++ trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-17 17:01:38 UTC (rev 9645)
@@ -36,7 +36,7 @@
this.nf = null;
}
- this.rtsf = new RTSFetcher("KSK@"+accprops.get("rtskey")+"-", inbound_dir);
+ this.rtsf = new RTSFetcher("KSK@"+accprops.get("rtskey")+"-", inbound_dir, accdir);
//this.mf = new MailFetcher(this.mb, inbound_dir, Freemail.getFCPConnection());
}
Modified: trunk/apps/Freemail/src/freemail/utils/ChainedAsymmetricBlockCipher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/utils/ChainedAsymmetricBlockCipher.java 2006-07-17 14:44:49 UTC (rev 9644)
+++ trunk/apps/Freemail/src/freemail/utils/ChainedAsymmetricBlockCipher.java 2006-07-17 17:01:38 UTC (rev 9645)
@@ -32,4 +32,8 @@
return bos.toByteArray();
}
+
+ public static byte[] decrypt(AsymmetricBlockCipher cipher, byte[] in) throws InvalidCipherTextException {
+ return ChainedAsymmetricBlockCipher.encrypt(cipher, in);
+ }
}
From dbkr at freenetproject.org Tue Jul 18 16:37:22 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Tue, 18 Jul 2006 16:37:22 +0000 (UTC)
Subject: [Freemail] r9652 - in trunk/apps/Freemail: docs/spec src/freemail
Message-ID: <20060718163722.681B69BD96@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-18 16:37:19 +0000 (Tue, 18 Jul 2006)
New Revision: 9652
Added:
trunk/apps/Freemail/src/freemail/InboundContact.java
Modified:
trunk/apps/Freemail/docs/spec/spec.tex
trunk/apps/Freemail/src/freemail/RTSFetcher.java
trunk/apps/Freemail/src/freemail/RTSLog.java
trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
Log:
Finish handling of RTS messages
Modified: trunk/apps/Freemail/docs/spec/spec.tex
===================================================================
--- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-18 10:43:32 UTC (rev 9651)
+++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-18 16:37:19 UTC (rev 9652)
@@ -20,11 +20,10 @@
A Freemail address comprises an arbitrary text string, followed by an '@' character. Following this is the mailsite address encoded in base 32 - that is, a valid Freenet uri that points to the mailsite. The URI must be base 32 encoded in order to make the address case insensitive to maintain compatability with traditional email clients. The string '.freenet' is appended to the whole address. An example Freemail address follows:
-bob at KVJUWQCMJ53UI6KEGJKFI2JQIZZFKY3XG\-4YE4QRSMUYWYV2PLJ4U27TLG\-R4DI3TLNZXW6QTSJIYCYNKS\-OR4XK23MGZDS2UDRKVCTIT\-BXJJWDQYKIOFM\-WC33VONTFOZTQMJZTS5LCO\-NEWGY3WGQWECUKBIJA\-UCRJPNVQWS3DTNF\-2GKLZNGEXQ.freemail
+bob at JRHXORDZIQZFIVDJ\-GBDHEVLDO43TATSCGJST\-C3CXJ5NHSTL6NM2HQ\-NDONNXG632COJFD\-ALBVKJ2HS5LLNQ3E\-OLKQOFKUKNCMG5F\-GYODBJBYVSYLPOVZ\-WMV3GOBRHGOLVMJ\-ZUSY3DOY2CY\-QKRIFBECQKF.freemail
+The base 32 encoded mailsite in this case is: LOwDyD2TTi0FrUcw70N\-B2e1lWOZyM~k4x4n\-knooBrJ0,5Rtyu\-kl6G-PqUE4L7\-Jl8aHqYaous\-fWfpbs9ubsI\-ccv4,AQABAAE
-The base 32 encoded mailsite in this case is: USK at LOwDyD2TTi0FrUcw70N\-B2e1lWOZyM~k4x4n\-knooBrJ0,5Rtyu\-kl6G-PqUE4L7\-Jl8aHqYaous\-fWfpbs9ubsI\-ccv4,AQABAAE/mailsite/-1/
-
(this is liable to change to make the addresses shorter)
Once the mailsite address has been obtained from the Freemail address, the string 'mailpage' is appended to obtain the URI for the mailpage. This mailpage contains all information required to contact the owner. The format of a mailpage is a 'Props File', which is used repeatedly in Freemail as a trivial format for storing short pieces of information. See section \ref{PropsFile}.
@@ -47,7 +46,7 @@
\item messagetype - This should be 'rts', to indicate that this message is an RTS.
\item to - The Freenet URI that appears encoded in Bob's Freemail address. This is necessary in order to prevent surreptitious forwarding to support the enryption explained later.
\item mailsite - Alice's mailsite URI
-\item ctsssk - A randomly generated KSK that Bob should insert to once he has recieved Alice's RTS message in order to acknoweldge that he is ready to recieve messages. This should be randomly generated and un-guessable so that only Bob knows which key to insert to.
+\item ctsksk - A randomly generated KSK that Bob should insert to once he has recieved Alice's RTS message in order to acknoweldge that he is ready to recieve messages. This should be randomly generated and un-guessable so that only Bob knows which key to insert to.
\end{itemize}
Following the last data item, there are two carriage-return-line-feeds, followed by Alice's signature. This is the SHA-256 hash of the message RSA encrypted with Alice's private key, included as raw bytes. The resulting message is then RSA encrypted with Bob's public key. If the resulting message is longer than a single RSA block, the message is encoded in chunks equal to the maximum block size and the ciphertext blocks are concatenated to form the final message.
@@ -63,14 +62,10 @@
\subsection{CTS Messages}
When Bob recieves an RTS message from Alice, he decrypts the message using his RSA private key. He then retrives the mailsite advertised in the RTS message. Having done this, he reads the signature on the end and decrypts the signature with the public key he just retrieved from the mailsite. He then calculates a SHA-256 checksum of the message and checks that his checksum is identical to the one he has decrypted. If it is not, he must discard the message. This ensures that the message is really from Alice. He must then read the 'to' field and ensure that its value is identical to his mailsite URI. If it is not, he must discard the message. This ensures that he is the intended recipient of the message.
-Bob then records the value of the 'commssk' key so that he can poll this SSK for messages periodicaly. Before doing so, he creates another propfile with the following values:
+Bob then records the value of the 'commssk' key so that he can poll this SSK for messages periodicaly.
-\begin{itemize}
-\item messagetype - This should be 'cts' to indicate that this is a clear-to-send message
-\end{itemize}
+Before doing so, Bob inserts some data to the value of the 'ctsksk' key in the RTS message. The data he inserts is irrelevant - the presence of the key is sufficient to prove to Alice that he has received the message. This completes Bob's part of the channel setup procedure.
-Bob inserts this file to the value of the 'ctsssk' key in the RTS message. This completes Bob's part of the channel setup procedure.
-
This message contains no valuable information and so does not need to be encrypted. It also does not need to be signed since only Alice and Bob know the KSK to which it must be inserted, so Alice knows that Bob must have inserted the message. The KSK that Bob inserts this message to tells Alice what RTS it relates to if there is any ambiguity.
Alice should check periodically for the insertion of this CTS message. If it does not arrive, Alice should re-send the RTS message with a different 'ctsssk', in order that she can be certain which RRS message any given CTS message corresponds to. All other field should be the same. The client may try several times before declaring the message undeliverable.
Added: trunk/apps/Freemail/src/freemail/InboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/InboundContact.java 2006-07-18 10:43:32 UTC (rev 9651)
+++ trunk/apps/Freemail/src/freemail/InboundContact.java 2006-07-18 16:37:19 UTC (rev 9652)
@@ -0,0 +1,30 @@
+package freemail;
+
+import java.io.File;
+
+import freemail.FreenetURI;
+import freemail.utils.PropsFile;
+
+public class InboundContact {
+ private static final String IBCT_PROPSFILE = "props";
+ private File ibct_dir;
+ private PropsFile ibct_props;
+
+ public InboundContact(File contact_dir, FreenetURI mailsite) {
+ this(contact_dir, mailsite.getKeyBody());
+ }
+
+ private InboundContact(File contact_dir, String keybody) {
+ this.ibct_dir = new File(contact_dir, keybody);
+
+ if (!this.ibct_dir.exists()) {
+ this.ibct_dir.mkdir();
+ }
+
+ this.ibct_props = new PropsFile(new File(this.ibct_dir, IBCT_PROPSFILE));
+ }
+
+ public void setProp(String key, String val) {
+ this.ibct_props.put(key, val);
+ }
+}
Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-18 10:43:32 UTC (rev 9651)
+++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-18 16:37:19 UTC (rev 9652)
@@ -20,6 +20,8 @@
import java.util.TimeZone;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.math.BigInteger;
+import java.net.MalformedURLException;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.crypto.params.RSAKeyParameters;
@@ -34,10 +36,12 @@
private File contact_dir;
private final SimpleDateFormat sdf;
private static final int POLL_AHEAD = 3;
- private static int PASSES_PER_DAY = 3;
- private static int MAX_DAYS_BACK = 30;
- private static String LOGFILE = "rtslog";
- private static int RTS_MAX_SIZE = 2 * 1024 * 1024;
+ private static final int PASSES_PER_DAY = 3;
+ private static final int MAX_DAYS_BACK = 30;
+ private static final String LOGFILE = "rtslog";
+ private static final int RTS_MAX_SIZE = 2 * 1024 * 1024;
+ private static final String RTS_UNPROC_PREFIX = "unprocessed_rts";
+ private static final int RTS_MAX_ATTEMPTS = 15;
private File accdir;
private PropsFile accprops;
@@ -49,8 +53,43 @@
this.accprops = AccountManager.getAccountFile(this.accdir);
}
- public void fetch() {
+ public void poll() {
+ this.fetch();
+ this.handle_unprocessed();
+ }
+
+ private void handle_unprocessed() {
+ File[] files = this.contact_dir.listFiles();
+
int i;
+ for (i = 0; i < files.length; i++) {
+ if (files[i].getName().startsWith(RTS_UNPROC_PREFIX)) {
+ if (this.handle_rts(files[i])) {
+ files[i].delete();
+ } else {
+ String[] parts = files[i].getName().split(":", 2);
+
+ int tries;
+ if (parts.length < 2) {
+ tries = 0;
+ } else {
+ tries = Integer.parseInt(parts[1]);
+ }
+ tries++;
+ if (tries > RTS_MAX_ATTEMPTS) {
+ System.out.println("Maximum attempts at handling RTS reached - deleting RTS");
+ files[i].delete();
+ } else {
+ File newname = new File(this.contact_dir, RTS_UNPROC_PREFIX + ":" + tries);
+ files[i].renameTo(newname);
+ }
+ }
+ }
+ }
+ }
+
+ private void fetch() {
+ int i;
RTSLog log = new RTSLog(new File(this.contact_dir, LOGFILE));
for (i = 1 - MAX_DAYS_BACK; i <= 0; i++) {
String datestr = DateStringFactory.getOffsetKeyString(i);
@@ -88,11 +127,14 @@
if (result != null) {
System.out.println(keybase+i+": got RTS!");
- // if we didn't successfully handle (or fatally fail to handle) the RTS message, don't increment the id, so we'll get it again in a bit
- if (this.handle_rts(result)) {
+
+ File rts_dest = new File(this.contact_dir, RTS_UNPROC_PREFIX + "-" + log.getAndIncUnprocNextId()+":0");
+
+ // stick this message in the RTS 'inbox'
+ if (result.renameTo(rts_dest)) {
+ // provided that worked, we can move on to the next RTS message
log.incNextId(date);
}
- result.delete();
} else {
System.out.println(keybase+i+": no RTS.");
}
@@ -122,8 +164,8 @@
return true;
}
- File rtsfile;
- byte[] sig;
+ File rtsfile = null;
+ byte[] their_encrypted_sig;
int messagebytes = 0;
try {
rtsfile = File.createTempFile("rtstmp", "tmp", Freemail.getTempDir());
@@ -148,20 +190,22 @@
// that's not right, we shouldn't have reached the end of the file, just the blank line before the signature
System.out.println("Couldn't find signature on RTS message - ignoring!");
+ rtsfile.delete();
return true;
}
- sig = new byte[bis.available()];
+ their_encrypted_sig = new byte[bis.available()];
int read = 0;
while (true) {
- read = bis.read(sig, 0, bis.available());
+ read = bis.read(their_encrypted_sig, 0, bis.available());
if (read == 0) break;
}
bis.close();
} catch (IOException ioe) {
System.out.println("IO error whilst handling RTS message. "+ioe.getMessage());
ioe.printStackTrace();
+ if (rtsfile != null) rtsfile.delete();
return false;
}
@@ -171,6 +215,7 @@
validate_rts(rtsprops);
} catch (Exception e) {
System.out.println("RTS message does not contain vital information: "+e.getMessage()+" - discarding");
+ rtsfile.delete();
return true;
}
@@ -182,22 +227,99 @@
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException alge) {
System.out.println("No MD5 implementation available - sorry, Freemail cannot work!");
+ rtsfile.delete();
return false;
}
md.update(plaintext, 0, messagebytes);
byte[] our_hash = md.digest();
HighLevelFCPClient fcpcli = new HighLevelFCPClient();
- fcpcli.fetch(their_mailsite);
- // TODO: finish.
+ File msfile = fcpcli.fetch(their_mailsite);
+ if (msfile == null) {
+ // oh well, try again in a bit
+ return false;
+ }
- // verify the message is for us
+ PropsFile mailsite = new PropsFile(msfile);
+ String their_exponent = mailsite.get("asymkey.pubexponent");
+ String their_modulus = mailsite.get("asymkey.modulus");
+ if (their_exponent == null || their_modulus == null) {
+ System.out.println("Mailsite fetched successfully but missing vital information! Discarding this RTS.");
+ msfile.delete();
+ rtsfile.delete();
+ return true;
+ }
+
+ RSAKeyParameters their_pubkey = new RSAKeyParameters(false, new BigInteger(their_modulus, 10), new BigInteger(their_exponent, 10));
+ AsymmetricBlockCipher deccipher = new RSAEngine();
+ deccipher.init(false, their_pubkey);
+
+ byte[] their_hash;
+ try {
+ their_hash = deccipher.processBlock(their_encrypted_sig, 0, their_encrypted_sig.length);
+ } catch (InvalidCipherTextException icte) {
+ System.out.println("It was not possible to decrypt the signature of this RTS message. Discarding the RTS message.");
+ msfile.delete();
+ rtsfile.delete();
+ return true;
+ }
+
+ // finally we can now check that our hash and their hash
+ // match!
+ if (their_hash.length != our_hash.length) {
+ System.out.println("The signature of the RTS message is not valid. Discarding the RTS message.");
+ msfile.delete();
+ rtsfile.delete();
+ return true;
+ }
+ int i;
+ for (i = 0; i < their_hash.length; i++) {
+ if (their_hash[i] != our_hash[i]) {
+ System.out.println("The signature of the RTS message is not valid. Discarding the RTS message.");
+ msfile.delete();
+ rtsfile.delete();
+ return true;
+ }
+ }
+ // the signature is valid! Hooray!
+ // Now verify the message is for us
+ String our_mailsite_keybody;
+ try {
+ our_mailsite_keybody = new FreenetURI(this.accprops.get("mailsite.pubkey")).getKeyBody();
+ } catch (MalformedURLException mfue) {
+ System.out.println("Local mailsite URI is invalid! Corrupt account file?");
+ msfile.delete();
+ rtsfile.delete();
+ return false;
+ }
+ if (!rtsprops.get("to").equals(our_mailsite_keybody)) {
+ System.out.println("Recieved an RTS message that was not intended for the recipient. Discarding.");
+ msfile.delete();
+ rtsfile.delete();
+ return true;
+ }
+
// create the inbound contact
+ FreenetURI their_mailsite_furi;
+ try {
+ their_mailsite_furi = new FreenetURI(their_mailsite);
+ } catch (MalformedURLException mfue) {
+ System.out.println("Mailsite in the RTS message is not a valid Freenet URI. Discarding RTS message.");
+ msfile.delete();
+ rtsfile.delete();
+ return true;
+ }
+ InboundContact ibct = new InboundContact(this.contact_dir, their_mailsite_furi);
- // move the props file to the right place
+ ibct.setProp("commssk", rtsprops.get("commssk"));
+ ibct.setProp("ackssk", rtsprops.get("ackssk"));
+ ibct.setProp("ctsksk", rtsprops.get("ctsksk"));
+ msfile.delete();
+ rtsfile.delete();
+
return true;
}
@@ -229,7 +351,7 @@
if (rts.get("commssk") == null) {
missing.append("commssk");
}
- if (rts.get("ackssk") == null) {
+ if (rts.get("ackksk") == null) {
missing.append("ackssk");
}
if (rts.get("messagetype") == null) {
@@ -241,7 +363,7 @@
if (rts.get("mailsite") == null) {
missing.append("mailsite");
}
- if (rts.get("ctsssk") == null) {
+ if (rts.get("ctsksk") == null) {
missing.append("ctsssk");
}
Modified: trunk/apps/Freemail/src/freemail/RTSLog.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSLog.java 2006-07-18 10:43:32 UTC (rev 9651)
+++ trunk/apps/Freemail/src/freemail/RTSLog.java 2006-07-18 16:37:19 UTC (rev 9652)
@@ -12,6 +12,7 @@
PropsFile logfile;
private static String NEXTID = "nextid-";
private static String PASSES = "passes-";
+ private static String UNPROC_NEXTID = "unproc-nextid";
public RTSLog(File f) {
this.logfile = new PropsFile(f);
@@ -27,7 +28,10 @@
}
public void incPasses(String day) {
- this.logfile.put(PASSES+day, Integer.toString(this.getPasses(PASSES+day) + 1));
+ int passes = this.getPasses(day);
+ passes++;
+
+ this.logfile.put(PASSES+day, Integer.toString(passes));
}
public void pruneBefore(Date keepafter) {
@@ -68,4 +72,18 @@
public void incNextId(String day) {
this.logfile.put(NEXTID+day, Integer.toString(this.getNextId(day) + 1));
}
+
+ public int getAndIncUnprocNextId() {
+ String nid = this.logfile.get(UNPROC_NEXTID);
+ int retval;
+ if (nid == null) {
+ retval = 1;
+ } else {
+ retval = Integer.parseInt(nid);
+ }
+
+ this.logfile.put(UNPROC_NEXTID, Integer.toString(retval + 1));
+
+ return retval;
+ }
}
Modified: trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-18 10:43:32 UTC (rev 9651)
+++ trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-18 16:37:19 UTC (rev 9652)
@@ -49,7 +49,7 @@
nf.fetch();
}
- this.rtsf.fetch();
+ this.rtsf.poll();
//mf.fetch_from_all();
From dbkr at freenetproject.org Wed Jul 19 11:59:25 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Wed, 19 Jul 2006 11:59:25 +0000 (UTC)
Subject: [Freemail] r9661 - trunk/apps/Freemail/src/freemail
Message-ID: <20060719115925.53AC29BC35@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-19 11:59:22 +0000 (Wed, 19 Jul 2006)
New Revision: 9661
Modified:
trunk/apps/Freemail/src/freemail/RTSFetcher.java
trunk/apps/Freemail/src/freemail/RTSLog.java
Log:
Fix modification whilst iterating, tidy up and more verbosity.
Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-19 02:14:57 UTC (rev 9660)
+++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-19 11:59:22 UTC (rev 9661)
@@ -63,26 +63,26 @@
int i;
for (i = 0; i < files.length; i++) {
- if (files[i].getName().startsWith(RTS_UNPROC_PREFIX)) {
- if (this.handle_rts(files[i])) {
+ if (!files[i].getName().startsWith(RTS_UNPROC_PREFIX))
+ continue;
+ if (this.handle_rts(files[i])) {
+ files[i].delete();
+ } else {
+ String[] parts = files[i].getName().split(":", 2);
+
+ int tries;
+ if (parts.length < 2) {
+ tries = 0;
+ } else {
+ tries = Integer.parseInt(parts[1]);
+ }
+ tries++;
+ if (tries > RTS_MAX_ATTEMPTS) {
+ System.out.println("Maximum attempts at handling RTS reached - deleting RTS");
files[i].delete();
} else {
- String[] parts = files[i].getName().split(":", 2);
-
- int tries;
- if (parts.length < 2) {
- tries = 0;
- } else {
- tries = Integer.parseInt(parts[1]);
- }
- tries++;
- if (tries > RTS_MAX_ATTEMPTS) {
- System.out.println("Maximum attempts at handling RTS reached - deleting RTS");
- files[i].delete();
- } else {
- File newname = new File(this.contact_dir, RTS_UNPROC_PREFIX + ":" + tries);
- files[i].renameTo(newname);
- }
+ File newname = new File(this.contact_dir, RTS_UNPROC_PREFIX + ":" + tries);
+ files[i].renameTo(newname);
}
}
}
@@ -164,6 +164,8 @@
return true;
}
+ System.out.println("RTS decrypted to: "+new String(plaintext));
+
File rtsfile = null;
byte[] their_encrypted_sig;
int messagebytes = 0;
@@ -235,6 +237,8 @@
HighLevelFCPClient fcpcli = new HighLevelFCPClient();
+ System.out.println("Trying to fetch sender's mailsite: "+their_mailsite);
+
File msfile = fcpcli.fetch(their_mailsite);
if (msfile == null) {
// oh well, try again in a bit
@@ -283,6 +287,7 @@
return true;
}
}
+ System.out.println("Signature valid :)");
// the signature is valid! Hooray!
// Now verify the message is for us
String our_mailsite_keybody;
@@ -301,6 +306,8 @@
return true;
}
+ System.out.println("Original message intended for us :)");
+
// create the inbound contact
FreenetURI their_mailsite_furi;
try {
@@ -320,6 +327,8 @@
msfile.delete();
rtsfile.delete();
+ System.out.println("Inbound contact created!");
+
return true;
}
Modified: trunk/apps/Freemail/src/freemail/RTSLog.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSLog.java 2006-07-19 02:14:57 UTC (rev 9660)
+++ trunk/apps/Freemail/src/freemail/RTSLog.java 2006-07-19 11:59:22 UTC (rev 9661)
@@ -3,6 +3,8 @@
import java.util.Date;
import java.util.Set;
import java.util.Iterator;
+import java.util.Vector;
+import java.util.Enumeration;
import java.io.File;
import freemail.utils.PropsFile;
@@ -36,6 +38,7 @@
public void pruneBefore(Date keepafter) {
Set props = this.logfile.listProps();
+ Vector hitlist = new Vector();
Iterator i = props.iterator();
while (i.hasNext()) {
@@ -53,11 +56,18 @@
Date logdate = DateStringFactory.DateFromKeyString(datestr);
if (logdate == null) {
// couldn't parse the date... hmm
- this.logfile.remove(cur);
+ hitlist.add(cur);
} else if (logdate.before(keepafter)) {
- this.logfile.remove(cur);
+ hitlist.add(cur);
}
}
+
+ Enumeration e = hitlist.elements();
+ while (e.hasMoreElements()) {
+ String victim = (String) e.nextElement();
+
+ this.logfile.remove(victim);
+ }
}
public int getNextId(String day) {
From dbkr at freenetproject.org Wed Jul 19 12:21:04 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Wed, 19 Jul 2006 12:21:04 +0000 (UTC)
Subject: [Freemail] r9662 - trunk/apps/Freemail/src/freemail
Message-ID: <20060719122104.B016D9BD8C@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-19 12:21:02 +0000 (Wed, 19 Jul 2006)
New Revision: 9662
Modified:
trunk/apps/Freemail/src/freemail/OutboundContact.java
Log:
Glad I noticed that before spending hours debugging it...
Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-19 11:59:22 UTC (rev 9661)
+++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-19 12:21:02 UTC (rev 9662)
@@ -187,7 +187,7 @@
enccipher.init(true, their_pub_key);
byte[] encmsg = null;
try {
- encmsg = ChainedAsymmetricBlockCipher.encrypt(sigcipher, bos.toByteArray());
+ encmsg = ChainedAsymmetricBlockCipher.encrypt(enccipher, bos.toByteArray());
} catch (InvalidCipherTextException e) {
e.printStackTrace();
return false;
From dbkr at freenetproject.org Thu Jul 20 12:07:44 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Thu, 20 Jul 2006 12:07:44 +0000 (UTC)
Subject: [Freemail] r9670 - trunk/apps/Freemail/src/freemail
Message-ID: <20060720120744.1F6EC9C74B@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-20 12:07:41 +0000 (Thu, 20 Jul 2006)
New Revision: 9670
Modified:
trunk/apps/Freemail/src/freemail/AccountManager.java
trunk/apps/Freemail/src/freemail/OutboundContact.java
trunk/apps/Freemail/src/freemail/RTSFetcher.java
Log:
More on RTS messages (bugfixes and things added to the spec later)
Modified: trunk/apps/Freemail/src/freemail/AccountManager.java
===================================================================
--- trunk/apps/Freemail/src/freemail/AccountManager.java 2006-07-20 01:52:32 UTC (rev 9669)
+++ trunk/apps/Freemail/src/freemail/AccountManager.java 2006-07-20 12:07:41 UTC (rev 9670)
@@ -138,7 +138,7 @@
throw new IOException("Unable to write account file");
}
- // initialise RTS/CTS KSK
+ // initialise RTS KSK
Random rnd = new Random();
String rtskey = new String();
Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-20 01:52:32 UTC (rev 9669)
+++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-20 12:07:41 UTC (rev 9670)
@@ -7,6 +7,7 @@
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.util.Random;
import freemail.utils.EmailAddress;
import freemail.utils.PropsFile;
@@ -25,6 +26,7 @@
private final File accdir;
private final EmailAddress address;
private static final String OUTBOUND_DIR = "outbound";
+ private static final int CTS_KSK_LENGTH = 32;
public OutboundContact(File accdir, EmailAddress a) throws BadFreemailAddressException {
this.address = a;
@@ -76,13 +78,29 @@
this.contactfile.put("commssk.pubkey", ssk.pubkey);
// we've just generated a new SSK, so the other party definately doesn't know about it
this.contactfile.put("status", "notsent");
- } else {
- ssk = new SSKKeyPair();
}
return ssk;
}
+ private SSKKeyPair getAckKeyPair() {
+ SSKKeyPair ssk = new SSKKeyPair();
+
+ ssk.pubkey = this.contactfile.get("ackssk.privkey");
+ ssk.privkey = this.contactfile.get("ackssk.pubkey");
+
+
+ if (ssk.pubkey == null || ssk.privkey == null) {
+ HighLevelFCPClient cli = new HighLevelFCPClient();
+ ssk = cli.makeSSK();
+
+ this.contactfile.put("ackssk.privkey", ssk.privkey);
+ this.contactfile.put("ackssk.pubkey", ssk.pubkey);
+ }
+
+ return ssk;
+ }
+
private RSAKeyParameters getPubKey() throws OutboundContactFatalException {
String mod_str = this.contactfile.get("asymkey.modulus");
String exp_str = this.contactfile.get("asymkey.pubexponent");
@@ -123,8 +141,9 @@
*/
public boolean init() throws OutboundContactFatalException {
// try to fetch get all necessary info. will fetch mailsite / generate new keys if necessary
- SSKKeyPair ssk = this.getCommKeyPair();
- if (ssk == null) return false;
+ SSKKeyPair commssk = this.getCommKeyPair();
+ if (commssk == null) return false;
+ SSKKeyPair ackssk = this.getAckKeyPair();
RSAKeyParameters their_pub_key = this.getPubKey();
if (their_pub_key == null) return false;
String rtsksk = this.getRtsKsk();
@@ -134,8 +153,20 @@
// the public part of the SSK keypair we generated
// put this first to avoid messages with the same first block, since we don't (currently) use CBC
- rtsmessage.append("commssk="+ssk.pubkey+"\r\n");
+ rtsmessage.append("commssk="+commssk.pubkey+"\r\n");
+ rtsmessage.append("ackssk="+ackssk.privkey+"\r\n");
+
+ Random rnd = new Random();
+ String ctsksk = new String("KSK@");
+
+ int i;
+ for (i = 0; i < CTS_KSK_LENGTH; i++) {
+ ctsksk += (char)(rnd.nextInt(25) + (int)'a');
+ }
+
+ rtsmessage.append("ctsksk="+ctsksk+"\r\n");
+
rtsmessage.append("messagetype=rts\r\n");
// must include who this RTS is to, otherwise we're vulnerable to surruptitious forwarding
Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-20 01:52:32 UTC (rev 9669)
+++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-20 12:07:41 UTC (rev 9670)
@@ -164,8 +164,6 @@
return true;
}
- System.out.println("RTS decrypted to: "+new String(plaintext));
-
File rtsfile = null;
byte[] their_encrypted_sig;
int messagebytes = 0;
@@ -182,6 +180,7 @@
messagebytes += lis.getLastBytesRead();
if (line == null || line.equals("")) break;
+ System.out.println(line);
ps.println(line);
}
@@ -198,11 +197,15 @@
their_encrypted_sig = new byte[bis.available()];
- int read = 0;
+ int totalread = 0;
while (true) {
- read = bis.read(their_encrypted_sig, 0, bis.available());
- if (read == 0) break;
+ int read = bis.read(their_encrypted_sig, totalread, bis.available());
+ if (read <= 0) break;
+ totalread += read;
}
+
+ System.out.println("read "+totalread+" bytes of signature");
+
bis.close();
} catch (IOException ioe) {
System.out.println("IO error whilst handling RTS message. "+ioe.getMessage());
@@ -211,6 +214,8 @@
return false;
}
+
+
PropsFile rtsprops = new PropsFile(rtsfile);
try {
@@ -358,25 +363,25 @@
StringBuffer missing = new StringBuffer();
if (rts.get("commssk") == null) {
- missing.append("commssk");
+ missing.append("commssk, ");
}
- if (rts.get("ackksk") == null) {
- missing.append("ackssk");
+ if (rts.get("ackssk") == null) {
+ missing.append("ackssk, ");
}
if (rts.get("messagetype") == null) {
- missing.append("messagetype");
+ missing.append("messagetype, ");
}
if (rts.get("to") == null) {
- missing.append("to");
+ missing.append("to, ");
}
if (rts.get("mailsite") == null) {
- missing.append("mailsite");
+ missing.append("mailsite, ");
}
if (rts.get("ctsksk") == null) {
- missing.append("ctsssk");
+ missing.append("ctsksk, ");
}
if (missing.length() == 0) return;
- throw new Exception(missing.toString());
+ throw new Exception(missing.toString().substring(0, missing.length() - 2));
}
}
From dbkr at freenetproject.org Thu Jul 20 13:34:15 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Thu, 20 Jul 2006 13:34:15 +0000 (UTC)
Subject: [Freemail] r9671 - trunk/apps/Freemail/src/freemail
Message-ID: <20060720133415.69F9A9BCF9@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-20 13:34:13 +0000 (Thu, 20 Jul 2006)
New Revision: 9671
Modified:
trunk/apps/Freemail/src/freemail/RTSFetcher.java
Log:
Working RTS messages :)
Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-20 12:07:41 UTC (rev 9670)
+++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-20 13:34:13 UTC (rev 9671)
@@ -227,14 +227,13 @@
}
// verify the signature
- String their_mailsite = rtsprops.get("mailsite");
+ String their_mailsite_raw = rtsprops.get("mailsite");
- MessageDigest md;
+ MessageDigest md = null;
try {
- md = MessageDigest.getInstance("MD5");
+ md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException alge) {
- System.out.println("No MD5 implementation available - sorry, Freemail cannot work!");
- rtsfile.delete();
+ System.out.println("No SHA 256 implementation available - Freemail cannot work!");
return false;
}
md.update(plaintext, 0, messagebytes);
@@ -242,6 +241,23 @@
HighLevelFCPClient fcpcli = new HighLevelFCPClient();
+ FreenetURI their_mailsite_furi;
+ try {
+ their_mailsite_furi = new FreenetURI(their_mailsite_raw);
+ } catch (MalformedURLException mfue) {
+ System.out.println("Mailsite in the RTS message is not a valid Freenet URI. Discarding RTS message.");
+ rtsfile.delete();
+ return true;
+ }
+
+ String their_mailsite = "USK@"+their_mailsite_furi.getKeyBody()+"/"+their_mailsite_furi.getSuffix();
+
+ if (!their_mailsite.endsWith("/")) {
+ their_mailsite += "/";
+ }
+ their_mailsite += "1/"+MailSite.MAILPAGE;
+
+
System.out.println("Trying to fetch sender's mailsite: "+their_mailsite);
File msfile = fcpcli.fetch(their_mailsite);
@@ -278,7 +294,7 @@
// finally we can now check that our hash and their hash
// match!
if (their_hash.length != our_hash.length) {
- System.out.println("The signature of the RTS message is not valid. Discarding the RTS message.");
+ System.out.println("The signature of the RTS message is not valid (our hash: "+our_hash.length+"bytes, their hash: "+their_hash.length+"bytes. Discarding the RTS message.");
msfile.delete();
rtsfile.delete();
return true;
@@ -314,15 +330,6 @@
System.out.println("Original message intended for us :)");
// create the inbound contact
- FreenetURI their_mailsite_furi;
- try {
- their_mailsite_furi = new FreenetURI(their_mailsite);
- } catch (MalformedURLException mfue) {
- System.out.println("Mailsite in the RTS message is not a valid Freenet URI. Discarding RTS message.");
- msfile.delete();
- rtsfile.delete();
- return true;
- }
InboundContact ibct = new InboundContact(this.contact_dir, their_mailsite_furi);
ibct.setProp("commssk", rtsprops.get("commssk"));
From dbkr at freenetproject.org Sat Jul 22 23:57:30 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Sat, 22 Jul 2006 23:57:30 +0000 (UTC)
Subject: [Freemail] r9729 - in trunk/apps/Freemail/src: freemail
freemail/fcp freemail/imap freemail/smtp freemail/utils
freenet/support/io
Message-ID: <20060722235730.2CB999C909@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-22 23:57:24 +0000 (Sat, 22 Jul 2006)
New Revision: 9729
Added:
trunk/apps/Freemail/src/freemail/AckProcrastinator.java
Modified:
trunk/apps/Freemail/src/freemail/AccountManager.java
trunk/apps/Freemail/src/freemail/BadFreemailAddressException.java
trunk/apps/Freemail/src/freemail/Freemail.java
trunk/apps/Freemail/src/freemail/InboundContact.java
trunk/apps/Freemail/src/freemail/MailSite.java
trunk/apps/Freemail/src/freemail/MessageSender.java
trunk/apps/Freemail/src/freemail/NIMFetcher.java
trunk/apps/Freemail/src/freemail/OutboundContact.java
trunk/apps/Freemail/src/freemail/OutboundContactFatalException.java
trunk/apps/Freemail/src/freemail/RTSFetcher.java
trunk/apps/Freemail/src/freemail/fcp/FCPBadFileException.java
trunk/apps/Freemail/src/freemail/fcp/NoNodeConnectionException.java
trunk/apps/Freemail/src/freemail/imap/IMAPBadMessageException.java
trunk/apps/Freemail/src/freemail/smtp/SMTPBadCommandException.java
trunk/apps/Freemail/src/freemail/utils/EmailAddress.java
trunk/apps/Freemail/src/freemail/utils/PropsFile.java
trunk/apps/Freemail/src/freenet/support/io/TooLongException.java
Log:
* Insert ACKs (CTS messages), delayed by a random amount of time
* Use bouncycastle's digest functions so it works with GCJ out of the box
* Tidy up unused imports that should have been committed separately for want of Internet access at the time.
Modified: trunk/apps/Freemail/src/freemail/AccountManager.java
===================================================================
--- trunk/apps/Freemail/src/freemail/AccountManager.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/AccountManager.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,17 +1,14 @@
package freemail;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.math.BigInteger;
+import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
@@ -72,12 +69,7 @@
}
public static void ChangePassword(String username, String newpassword) throws Exception {
- MessageDigest md = null;
- try {
- md = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException alge) {
- throw new Exception("No MD5 implementation available - sorry, Freemail cannot work!");
- }
+ MD5Digest md5 = new MD5Digest();
File accountdir = new File(DATADIR, username);
if (!accountdir.exists()) {
@@ -86,7 +78,9 @@
PropsFile accfile = getAccountFile(accountdir);
- byte[] md5passwd = md.digest(newpassword.getBytes());
+ md5.update(newpassword.getBytes(), 0, newpassword.getBytes().length);
+ byte[] md5passwd = new byte[md5.getDigestSize()];
+ md5.doFinal(md5passwd, 0);
String strmd5 = new String(Hex.encode(md5passwd));
accfile.put("md5passwd", strmd5);
@@ -197,14 +191,10 @@
String realmd5str = accfile.get("md5passwd");
if (realmd5str == null) return false;
- MessageDigest md = null;
- try {
- md = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException alge) {
- System.out.println("No MD5 implementation available - logins will not work!");
- return false;
- }
- byte[] givenmd5 = md.digest(password.getBytes());
+ MD5Digest md5 = new MD5Digest();
+ md5.update(password.getBytes(), 0, password.getBytes().length);
+ byte[] givenmd5 = new byte[md5.getDigestSize()];
+ md5.doFinal(givenmd5, 0);
String givenmd5str = new String(Hex.encode(givenmd5));
Added: trunk/apps/Freemail/src/freemail/AckProcrastinator.java
===================================================================
--- trunk/apps/Freemail/src/freemail/AckProcrastinator.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/AckProcrastinator.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -0,0 +1,106 @@
+package freemail;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+import java.lang.InterruptedException;
+import java.util.Random;
+
+import freemail.utils.PropsFile;
+import freemail.fcp.HighLevelFCPClient;
+import freemail.fcp.FCPBadFileException;
+
+/** Takes simple pieces of data to insert to keys and inserts them at some point
+ * randomly within a given time frame in order to disguise the time at which messages
+ * were received. This is by no means infalliable, and will only work effectively if
+ * Freemail is run more or less permanantly.
+ */
+public class AckProcrastinator implements Runnable {
+ private static final long MAX_DELAY = 12 * 60 * 60 * 1000;
+
+ private static File ackdir;
+ private static Random rnd;
+
+ public AckProcrastinator() {
+ rnd = new Random();
+ File ackdir = getAckDir();
+ if (!ackdir.exists()) {
+ ackdir.mkdir();
+ }
+ }
+
+ private static File getAckDir() {
+ return AckProcrastinator.ackdir;
+ }
+
+ public static void setAckDir(File dir) {
+ AckProcrastinator.ackdir = dir;
+ if (!dir.exists()) {
+ dir.mkdir();
+ }
+ }
+
+ public void run() {
+ while (true) {
+ File[] acks = getAckDir().listFiles();
+
+ int i;
+ for (i = 0; i < acks.length; i++) {
+ PropsFile ack = new PropsFile(acks[i]);
+
+ String s_it = ack.get("nominalInsertTime");
+ String key = ack.get("key");
+ String data = ack.get("data");
+ if (s_it == null || key == null || data == null) {
+ acks[i].delete();
+ continue;
+ }
+ long instime = Long.parseLong(s_it);
+
+ if (instime < System.currentTimeMillis()) {
+ HighLevelFCPClient fcpcli = new HighLevelFCPClient();
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(data.getBytes());
+
+ try {
+ if (fcpcli.put(bis, key) != null)
+ acks[i].delete();
+ } catch (FCPBadFileException bfe) {
+ // won't occur
+ }
+ }
+ }
+
+ try {
+ Thread.sleep(2 * 60 * 1000);
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+
+ /** Insert some data at some random point in the future, but ideally before
+ * 'by' (in milliseconds).
+ */
+ public static synchronized void put(String key, String data) {
+ // this could be a parameter if desired in the future
+ long by = System.currentTimeMillis() + MAX_DELAY;
+
+ try {
+ PropsFile ackfile= new PropsFile(File.createTempFile("delayed-ack", "", getAckDir()));
+
+ ackfile.put("key", key);
+ ackfile.put("data", data);
+ ackfile.put("by", Long.toString(by));
+
+ long insertTime = System.currentTimeMillis();
+
+ insertTime += rnd.nextFloat() * by;
+
+ ackfile.put("nominalInsertTime", Long.toString(insertTime));
+ } catch (IOException ioe) {
+ System.out.println("IO Error whilst trying to schedule ACK for insertion! ACK will not be inserted!");
+ ioe.printStackTrace();
+ }
+
+ }
+}
Modified: trunk/apps/Freemail/src/freemail/BadFreemailAddressException.java
===================================================================
--- trunk/apps/Freemail/src/freemail/BadFreemailAddressException.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/BadFreemailAddressException.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,5 +1,5 @@
package freemail;
public class BadFreemailAddressException extends Exception {
-
+ static final long serialVersionUID = -1;
}
Modified: trunk/apps/Freemail/src/freemail/Freemail.java
===================================================================
--- trunk/apps/Freemail/src/freemail/Freemail.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/Freemail.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -10,6 +10,9 @@
public class Freemail {
private static final String TEMPDIRNAME = "temp";
+ private static final String DATADIR = "data";
+ private static final String GLOBALDATADIR = "globaldata";
+ private static final String ACKDIR = "delayedacks";
private static File datadir;
private static File tempdir;
private static FCPConnection fcpconn;
@@ -99,8 +102,13 @@
return;
}
+ File globaldatadir = new File(GLOBALDATADIR);
+ if (!globaldatadir.exists()) {
+ globaldatadir.mkdir();
+ }
+
// start a SingleAccountWatcher for each account
- Freemail.datadir = new File("data");
+ Freemail.datadir = new File(DATADIR);
if (!Freemail.datadir.exists()) {
System.out.println("Starting Freemail for the first time.");
System.out.println("You will probably want to add an account by running Freemail with arguments --newaccount ");
@@ -122,23 +130,32 @@
if (files[i].getName().equals(".") || files[i].getName().equals(".."))
continue;
- Thread t = new Thread(new SingleAccountWatcher(files[i]));
+ Thread t = new Thread(new SingleAccountWatcher(files[i]), "Account Watcher for "+files[i].getName());
t.setDaemon(true);
t.start();
}
// and a sender thread
MessageSender sender = new MessageSender(Freemail.datadir);
- Thread senderthread = new Thread(sender);
+ Thread senderthread = new Thread(sender, "Message sender");
senderthread.setDaemon(true);
senderthread.start();
// start the SMTP Listener
SMTPListener smtpl = new SMTPListener(sender);
- Thread smtpthread = new Thread(smtpl);
+ Thread smtpthread = new Thread(smtpl, "SMTP Listener");
smtpthread.setDaemon(true);
smtpthread.start();
+ // start the delayed ACK inserter
+ File ackdir = new File(globaldatadir, ACKDIR);
+ AckProcrastinator.setAckDir(ackdir);
+ AckProcrastinator ackinserter = new AckProcrastinator();
+ Thread ackinsthread = new Thread(ackinserter, "Delayed ACK Inserter");
+ ackinsthread.setDaemon(true);
+ ackinsthread.start();
+
+
// start the IMAP listener
IMAPListener imapl = new IMAPListener();
imapl.run();
Modified: trunk/apps/Freemail/src/freemail/InboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/InboundContact.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/InboundContact.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -27,4 +27,8 @@
public void setProp(String key, String val) {
this.ibct_props.put(key, val);
}
+
+ public String getProp(String key) {
+ return this.ibct_props.get(key);
+ }
}
Modified: trunk/apps/Freemail/src/freemail/MailSite.java
===================================================================
--- trunk/apps/Freemail/src/freemail/MailSite.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/MailSite.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,6 +1,5 @@
package freemail;
-import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import freemail.utils.PropsFile;
@@ -66,7 +65,7 @@
minslot = 1;
}
- int actualslot = cli.SlotInsert(mailpage, key, 1, "/"+MAILPAGE);
+ int actualslot = cli.SlotInsert(mailpage, key, minslot, "/"+MAILPAGE);
this.accprops.put("mailsite.slot", new Integer(actualslot).toString());
Modified: trunk/apps/Freemail/src/freemail/MessageSender.java
===================================================================
--- trunk/apps/Freemail/src/freemail/MessageSender.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/MessageSender.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -3,14 +3,11 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Vector;
import java.util.Enumeration;
import freemail.fcp.HighLevelFCPClient;
-import freemail.fcp.FCPInsertErrorMessage;
-import freemail.fcp.FCPBadFileException;
import freemail.utils.EmailAddress;
import freemail.utils.DateStringFactory;
Modified: trunk/apps/Freemail/src/freemail/NIMFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/NIMFetcher.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/NIMFetcher.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,6 +1,5 @@
package freemail;
-import freemail.fcp.FCPConnection;
import freemail.fcp.HighLevelFCPClient;
import freemail.utils.DateStringFactory;
@@ -13,11 +12,7 @@
import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import org.bouncycastle.util.encoders.Hex;
-
public class NIMFetcher {
private final MessageBank mb;
private File contact_dir;
@@ -78,8 +73,8 @@
if (result != null) {
System.out.println(keybase+i+": got message!");
try {
- String checksum = this.storeMessage(result);
- log.addMessage(i, checksum);
+ this.storeMessage(result);
+ log.addMessage(i, "received");
} catch (IOException ioe) {
continue;
}
@@ -89,17 +84,9 @@
}
}
- private String storeMessage(File file) throws IOException {
+ private void storeMessage(File file) throws IOException {
MailMessage newmsg = this.mb.createMessage();
- MessageDigest md;
- try {
- md = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException alge) {
- System.out.println("No MD5 implementation available - can't checksum messages - not storing message.");
- return null;
- }
-
// add our own headers first
// recieved and date
newmsg.addHeader("Received", "(Freemail); "+this.sdf.format(new Date()));
@@ -118,8 +105,5 @@
newmsg.commit();
rdr.close();
file.delete();
-
- byte[] checksum = md.digest();
- return new String(Hex.encode(checksum));
}
}
Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -2,11 +2,8 @@
import java.io.File;
import java.io.ByteArrayOutputStream;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.util.Random;
import freemail.utils.EmailAddress;
@@ -16,6 +13,7 @@
import freemail.fcp.HighLevelFCPClient;
import freemail.fcp.SSKKeyPair;
+import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.engines.RSAEngine;
@@ -181,16 +179,11 @@
// sign the message
- MessageDigest md = null;
- try {
- md = MessageDigest.getInstance("SHA-256");
- } catch (NoSuchAlgorithmException alge) {
- System.out.println("No SHA 256 implementation available - no mail can be sent!");
- return false;
- }
+ SHA256Digest sha256 = new SHA256Digest();
+ sha256.update(rtsmessage.toString().getBytes(), 0, rtsmessage.toString().getBytes().length);
+ byte[] hash = new byte[sha256.getDigestSize()];
+ sha256.doFinal(hash, 0);
- byte[] hash = md.digest(rtsmessage.toString().getBytes());
-
RSAKeyParameters our_priv_key = AccountManager.getPrivateKey(this.accdir);
AsymmetricBlockCipher sigcipher = new RSAEngine();
Modified: trunk/apps/Freemail/src/freemail/OutboundContactFatalException.java
===================================================================
--- trunk/apps/Freemail/src/freemail/OutboundContactFatalException.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/OutboundContactFatalException.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,6 +1,7 @@
package freemail;
public class OutboundContactFatalException extends Exception {
+ static final long serialVersionUID = -1;
public OutboundContactFatalException(String msg) {
super(msg);
}
Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,6 +1,5 @@
package freemail;
-import freemail.fcp.FCPConnection;
import freemail.fcp.HighLevelFCPClient;
import freemail.utils.DateStringFactory;
import freemail.utils.PropsFile;
@@ -11,30 +10,25 @@
import java.io.FileOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.io.BufferedReader;
import java.io.PrintStream;
-import java.io.FileReader;
-import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.math.BigInteger;
import java.net.MalformedURLException;
-import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.InvalidCipherTextException;
import freenet.support.io.LineReadingInputStream;
+import freenet.support.io.TooLongException;
public class RTSFetcher {
private String rtskey;
private File contact_dir;
- private final SimpleDateFormat sdf;
private static final int POLL_AHEAD = 3;
private static final int PASSES_PER_DAY = 3;
private static final int MAX_DAYS_BACK = 30;
@@ -47,7 +41,6 @@
RTSFetcher(String key, File ctdir, File ad) {
this.rtskey = key;
- this.sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z");
this.contact_dir = ctdir;
this.accdir = ad;
this.accprops = AccountManager.getAccountFile(this.accdir);
@@ -176,7 +169,13 @@
String line;
while (true) {
- line = lis.readLine(200, 200);
+ try {
+ line = lis.readLine(200, 200);
+ } catch (TooLongException tle) {
+ System.out.println("RTS message has lines that are too long. Discarding.");
+ rtsfile.delete();
+ return true;
+ }
messagebytes += lis.getLastBytesRead();
if (line == null || line.equals("")) break;
@@ -229,15 +228,10 @@
// verify the signature
String their_mailsite_raw = rtsprops.get("mailsite");
- MessageDigest md = null;
- try {
- md = MessageDigest.getInstance("SHA-256");
- } catch (NoSuchAlgorithmException alge) {
- System.out.println("No SHA 256 implementation available - Freemail cannot work!");
- return false;
- }
- md.update(plaintext, 0, messagebytes);
- byte[] our_hash = md.digest();
+ SHA256Digest sha256 = new SHA256Digest();
+ sha256.update(plaintext, 0, messagebytes);
+ byte[] our_hash = new byte[sha256.getDigestSize()];
+ sha256.doFinal(our_hash, 0);
HighLevelFCPClient fcpcli = new HighLevelFCPClient();
@@ -334,8 +328,11 @@
ibct.setProp("commssk", rtsprops.get("commssk"));
ibct.setProp("ackssk", rtsprops.get("ackssk"));
- ibct.setProp("ctsksk", rtsprops.get("ctsksk"));
+ //ibct.setProp("ctsksk", rtsprops.get("ctsksk"));
+ // insert the cts at some point
+ AckProcrastinator.put(rtsprops.get("ctsksk"), "messagetype=cts");
+
msfile.delete();
rtsfile.delete();
Modified: trunk/apps/Freemail/src/freemail/fcp/FCPBadFileException.java
===================================================================
--- trunk/apps/Freemail/src/freemail/fcp/FCPBadFileException.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/fcp/FCPBadFileException.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,5 +1,5 @@
package freemail.fcp;
public class FCPBadFileException extends Exception {
-
+ static final long serialVersionUID = -1;
}
Modified: trunk/apps/Freemail/src/freemail/fcp/NoNodeConnectionException.java
===================================================================
--- trunk/apps/Freemail/src/freemail/fcp/NoNodeConnectionException.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/fcp/NoNodeConnectionException.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,6 +1,8 @@
package freemail.fcp;
public class NoNodeConnectionException extends Exception {
+ static final long serialVersionUID = -1;
+
NoNodeConnectionException() {
super();
}
Modified: trunk/apps/Freemail/src/freemail/imap/IMAPBadMessageException.java
===================================================================
--- trunk/apps/Freemail/src/freemail/imap/IMAPBadMessageException.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/imap/IMAPBadMessageException.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,5 +1,6 @@
package freemail.imap;;
public class IMAPBadMessageException extends Exception {
+ static final long serialVersionUID = -1;
// no, this isn't the most exciting class in the world.
}
Modified: trunk/apps/Freemail/src/freemail/smtp/SMTPBadCommandException.java
===================================================================
--- trunk/apps/Freemail/src/freemail/smtp/SMTPBadCommandException.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/smtp/SMTPBadCommandException.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,5 +1,5 @@
package freemail.smtp;
public class SMTPBadCommandException extends Exception {
-
+ static final long serialVersionUID = -1;
}
Modified: trunk/apps/Freemail/src/freemail/utils/EmailAddress.java
===================================================================
--- trunk/apps/Freemail/src/freemail/utils/EmailAddress.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/utils/EmailAddress.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -1,7 +1,5 @@
package freemail.utils;
-import org.bouncycastle.util.encoders.Hex;
-
import org.archive.util.Base32;
public class EmailAddress {
Modified: trunk/apps/Freemail/src/freemail/utils/PropsFile.java
===================================================================
--- trunk/apps/Freemail/src/freemail/utils/PropsFile.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freemail/utils/PropsFile.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -72,6 +72,7 @@
try {
this.write();
} catch (IOException ioe) {
+ ioe.printStackTrace();
return false;
}
return true;
Modified: trunk/apps/Freemail/src/freenet/support/io/TooLongException.java
===================================================================
--- trunk/apps/Freemail/src/freenet/support/io/TooLongException.java 2006-07-22 23:50:41 UTC (rev 9728)
+++ trunk/apps/Freemail/src/freenet/support/io/TooLongException.java 2006-07-22 23:57:24 UTC (rev 9729)
@@ -4,5 +4,5 @@
/** Exception thrown by a LineReadingInputStream when a line is too long. */
public class TooLongException extends IOException {
-
+ static final long serialVersionUID = -1;
}
\ No newline at end of file
From dbkr at freenetproject.org Sun Jul 23 14:17:00 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Sun, 23 Jul 2006 14:17:00 +0000 (UTC)
Subject: [Freemail] r9731 - in trunk/apps/Freemail/src/freemail: . utils
Message-ID: <20060723141700.C8BA59BE10@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-23 14:16:56 +0000 (Sun, 23 Jul 2006)
New Revision: 9731
Modified:
trunk/apps/Freemail/src/freemail/AckProcrastinator.java
trunk/apps/Freemail/src/freemail/MessageSender.java
trunk/apps/Freemail/src/freemail/OutboundContact.java
trunk/apps/Freemail/src/freemail/utils/EmailAddress.java
Log:
Send and poll for CTS messages, along with RTS retransmission
Modified: trunk/apps/Freemail/src/freemail/AckProcrastinator.java
===================================================================
--- trunk/apps/Freemail/src/freemail/AckProcrastinator.java 2006-07-23 04:17:59 UTC (rev 9730)
+++ trunk/apps/Freemail/src/freemail/AckProcrastinator.java 2006-07-23 14:16:56 UTC (rev 9731)
@@ -9,6 +9,7 @@
import freemail.utils.PropsFile;
import freemail.fcp.HighLevelFCPClient;
import freemail.fcp.FCPBadFileException;
+import freemail.fcp.FCPInsertErrorMessage;
/** Takes simple pieces of data to insert to keys and inserts them at some point
* randomly within a given time frame in order to disguise the time at which messages
@@ -62,9 +63,14 @@
ByteArrayInputStream bis = new ByteArrayInputStream(data.getBytes());
+ System.out.println("Inserting ack to "+key);
try {
- if (fcpcli.put(bis, key) != null)
+ FCPInsertErrorMessage err = fcpcli.put(bis, key);
+ if (err == null) {
acks[i].delete();
+ } else if (err.errorcode == FCPInsertErrorMessage.COLLISION) {
+ acks[i].delete();
+ }
} catch (FCPBadFileException bfe) {
// won't occur
}
Modified: trunk/apps/Freemail/src/freemail/MessageSender.java
===================================================================
--- trunk/apps/Freemail/src/freemail/MessageSender.java 2006-07-23 04:17:59 UTC (rev 9730)
+++ trunk/apps/Freemail/src/freemail/MessageSender.java 2006-07-23 14:16:56 UTC (rev 9731)
@@ -75,6 +75,7 @@
outbox.mkdir();
this.sendDir(files[i], outbox);
+ this.checkCTSs(files[i]);
}
// don't spin around the loop if nothing's
// going on
@@ -89,6 +90,21 @@
}
}
+ private void checkCTSs(File accdir) {
+ File contactsdir = new File(accdir, SingleAccountWatcher.CONTACTS_DIR);
+
+ File outbounddir = new File(contactsdir, OutboundContact.OUTBOUND_DIR);
+
+ File[] contacts = outbounddir.listFiles();
+
+ int i;
+ for (i = 0; i < contacts.length; i++) {
+ OutboundContact outboundcontact = new OutboundContact(accdir, contacts[i]);
+
+ outboundcontact.checkCTS();
+ }
+ }
+
private void sendDir(File accdir, File dir) {
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-23 04:17:59 UTC (rev 9730)
+++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-23 14:16:56 UTC (rev 9731)
@@ -13,6 +13,8 @@
import freemail.fcp.HighLevelFCPClient;
import freemail.fcp.SSKKeyPair;
+import org.archive.util.Base32;
+
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
@@ -20,11 +22,15 @@
import org.bouncycastle.crypto.InvalidCipherTextException;
public class OutboundContact {
+ public static final String OUTBOUND_DIR = "outbound";
private final PropsFile contactfile;
private final File accdir;
private final EmailAddress address;
- private static final String OUTBOUND_DIR = "outbound";
private static final int CTS_KSK_LENGTH = 32;
+ // how long to wait for a CTS before sending the message again
+ // slightly over 24 hours since some people are likley to fire Freemail
+ // up and roughly the same time every day
+ private static final long CTS_WAIT_TIME = 26 * 60 * 60 * 1000;
public OutboundContact(File accdir, EmailAddress a) throws BadFreemailAddressException {
this.address = a;
@@ -47,6 +53,69 @@
}
}
+ public OutboundContact(File accdir, File ctfile) {
+ this.accdir = accdir;
+ this.address = new EmailAddress();
+ this.address.domain = Base32.encode(ctfile.getName().getBytes())+".freemail";
+
+ this.contactfile = new PropsFile(ctfile);
+ }
+
+ public void checkCTS() {
+ String status = this.contactfile.get("status");
+ if (status == null) {
+ try {
+ this.init();
+ } catch (OutboundContactFatalException obctfe) {
+ // impossible
+ }
+ }
+
+ if (status.equals("cts-received")) {
+ return;
+ } else if (status.equals("rts-sent")) {
+ // poll for the CTS message
+
+ String ctsksk = this.contactfile.get("ctsksk");
+ if (ctsksk == null) {
+ try {
+ this.init();
+ } catch (OutboundContactFatalException obctfe) {
+ // impossible
+ }
+ }
+
+ HighLevelFCPClient fcpcli = new HighLevelFCPClient();
+
+ File cts = fcpcli.fetch(ctsksk);
+
+ if (cts == null) {
+ // haven't got the CTS message. should we give up yet?
+ String senttime = this.contactfile.get("rts-sent-at");
+
+ if (senttime == null || Long.parseLong(senttime) > System.currentTimeMillis() + CTS_WAIT_TIME) {
+ // yes, send another RTS
+ try {
+ this.init();
+ } catch (OutboundContactFatalException obctfe) {
+ // impossible
+ }
+ }
+
+ } else {
+ System.out.println("Sucessfully received CTS for "+this.address.getMailsiteKey());
+ cts.delete();
+ this.contactfile.put("status", "cts-received");
+ }
+ } else {
+ try {
+ this.init();
+ } catch (OutboundContactFatalException obctfe) {
+ // impossible
+ }
+ }
+ }
+
/*
* Whether or not we're ready to communicate with the other party
*/
@@ -131,6 +200,21 @@
return rtsksk;
}
+ private String getCTSKSK() {
+ String retval = this.contactfile.get("ctsksk");
+
+ if (retval != null) return retval;
+
+ Random rnd = new Random();
+ retval = new String("KSK@");
+
+ int i;
+ for (i = 0; i < CTS_KSK_LENGTH; i++) {
+ retval += (char)(rnd.nextInt(25) + (int)'a');
+ }
+ return retval;
+ }
+
/**
* Set up an outbound contact. Fetch the mailsite, generate a new SSK keypair and post an RTS message to the appropriate KSK.
* Will block for mailsite retrieval and RTS insertion
@@ -155,14 +239,9 @@
rtsmessage.append("ackssk="+ackssk.privkey+"\r\n");
- Random rnd = new Random();
- String ctsksk = new String("KSK@");
-
- int i;
- for (i = 0; i < CTS_KSK_LENGTH; i++) {
- ctsksk += (char)(rnd.nextInt(25) + (int)'a');
- }
+ String ctsksk = this.getCTSKSK();
+ this.contactfile.put("ctsksk", ctsksk);
rtsmessage.append("ctsksk="+ctsksk+"\r\n");
rtsmessage.append("messagetype=rts\r\n");
@@ -225,6 +304,8 @@
// remember the fact that we have successfully inserted the rts
this.contactfile.put("status", "rts-sent");
+ // and remember when we sent it!
+ this.contactfile.put("rts-sent-at", Long.toString(System.currentTimeMillis()));
return true;
}
Modified: trunk/apps/Freemail/src/freemail/utils/EmailAddress.java
===================================================================
--- trunk/apps/Freemail/src/freemail/utils/EmailAddress.java 2006-07-23 04:17:59 UTC (rev 9730)
+++ trunk/apps/Freemail/src/freemail/utils/EmailAddress.java 2006-07-23 14:16:56 UTC (rev 9731)
@@ -47,6 +47,9 @@
}
}
+ public EmailAddress() {
+ }
+
public boolean is_freemail_address() {
if (this.domain == null) return false;
if (!this.domain.endsWith(".freemail")) return false;
From dbkr at freenetproject.org Sun Jul 23 17:29:42 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Sun, 23 Jul 2006 17:29:42 +0000 (UTC)
Subject: [Freemail] r9736 - in trunk/apps/Freemail: docs/spec src/freemail
src/freemail/fcp
Message-ID: <20060723172942.C736C9C765@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-23 17:27:55 +0000 (Sun, 23 Jul 2006)
New Revision: 9736
Modified:
trunk/apps/Freemail/docs/spec/spec.tex
trunk/apps/Freemail/src/freemail/MailSite.java
trunk/apps/Freemail/src/freemail/MessageSender.java
trunk/apps/Freemail/src/freemail/OutboundContact.java
trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java
Log:
A few minor bits before starting on message exchange.
Modified: trunk/apps/Freemail/docs/spec/spec.tex
===================================================================
--- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-23 15:50:59 UTC (rev 9735)
+++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-23 17:27:55 UTC (rev 9736)
@@ -116,9 +116,9 @@
Then he might insert an acknowledgement to the key: \\
\\
\\
-SSK at AJoZbUvGkXlAJwI\-jdbu9BLPhpIXBu6\-w6nGwKYBnMfNLi,ACEgE1uUIzJdC\-Xcsz1yjgW45u\-Az-KuMrXBFYG\-U8maqc/ack-1 \\
+SSK at AJoZbUvGkXlAJwI\-jdbu9BLPhpIXBu6\-w6nGwKYBnMfNLi,ACEgE1uUIzJdC\-Xcsz1yjgW45u\-Az-KuMrXBFYG\-U8maqc/ack-657488664753 \\
\\
-The data that Bob publishes to this key is irrelevant - its mere existance in the network is sufficient to assert Bob's reciept of the message.
+The data that Bob publishes to this key is irrelevant - its mere existance in the network is sufficient to assert Bob's reciept of the message. If Alice has, for whatever reason, not received a CTS message from Bob, her receipt of a message ack should additionally be treated as receipt of a CTS message.
\appendix
Modified: trunk/apps/Freemail/src/freemail/MailSite.java
===================================================================
--- trunk/apps/Freemail/src/freemail/MailSite.java 2006-07-23 15:50:59 UTC (rev 9735)
+++ trunk/apps/Freemail/src/freemail/MailSite.java 2006-07-23 17:27:55 UTC (rev 9736)
@@ -67,6 +67,8 @@
int actualslot = cli.SlotInsert(mailpage, key, minslot, "/"+MAILPAGE);
+ if (actualslot < 0) return -1;
+
this.accprops.put("mailsite.slot", new Integer(actualslot).toString());
return actualslot;
Modified: trunk/apps/Freemail/src/freemail/MessageSender.java
===================================================================
--- trunk/apps/Freemail/src/freemail/MessageSender.java 2006-07-23 15:50:59 UTC (rev 9735)
+++ trunk/apps/Freemail/src/freemail/MessageSender.java 2006-07-23 17:27:55 UTC (rev 9736)
@@ -101,7 +101,10 @@
for (i = 0; i < contacts.length; i++) {
OutboundContact outboundcontact = new OutboundContact(accdir, contacts[i]);
- outboundcontact.checkCTS();
+ try {
+ outboundcontact.checkCTS();
+ } catch (OutboundContactFatalException obctfe) {
+ }
}
}
Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-23 15:50:59 UTC (rev 9735)
+++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2006-07-23 17:27:55 UTC (rev 9736)
@@ -61,14 +61,10 @@
this.contactfile = new PropsFile(ctfile);
}
- public void checkCTS() {
+ public void checkCTS() throws OutboundContactFatalException {
String status = this.contactfile.get("status");
if (status == null) {
- try {
- this.init();
- } catch (OutboundContactFatalException obctfe) {
- // impossible
- }
+ this.init();
}
if (status.equals("cts-received")) {
@@ -78,11 +74,7 @@
String ctsksk = this.contactfile.get("ctsksk");
if (ctsksk == null) {
- try {
- this.init();
- } catch (OutboundContactFatalException obctfe) {
- // impossible
- }
+ this.init();
}
HighLevelFCPClient fcpcli = new HighLevelFCPClient();
@@ -95,11 +87,7 @@
if (senttime == null || Long.parseLong(senttime) > System.currentTimeMillis() + CTS_WAIT_TIME) {
// yes, send another RTS
- try {
- this.init();
- } catch (OutboundContactFatalException obctfe) {
- // impossible
- }
+ this.init();
}
} else {
@@ -108,11 +96,7 @@
this.contactfile.put("status", "cts-received");
}
} else {
- try {
- this.init();
- } catch (OutboundContactFatalException obctfe) {
- // impossible
- }
+ this.init();
}
}
@@ -127,6 +111,7 @@
// don't wait for an ack before inserting the message, but be ready to insert it again
// if the ack never arrives
if (status.equals("rts-sent")) return true;
+ if (status.equals("cts-received")) return true;
return false;
}
Modified: trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java
===================================================================
--- trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-23 15:50:59 UTC (rev 9735)
+++ trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2006-07-23 17:27:55 UTC (rev 9736)
@@ -13,20 +13,19 @@
private final MessageBank mb;
private final NIMFetcher nf;
private final RTSFetcher rtsf;
+ private long mailsite_last_upload;
+ private final PropsFile accprops;
SingleAccountWatcher(File accdir) {
+ this.accprops = AccountManager.getAccountFile(accdir);
File contacts_dir = new File(accdir, CONTACTS_DIR);
File inbound_dir = new File(contacts_dir, INBOUND_DIR);
+ this.mailsite_last_upload = 0;
if (!inbound_dir.exists()) {
inbound_dir.mkdir();
}
- // TODO: do this in the loop, periodically
- PropsFile accprops = AccountManager.getAccountFile(accdir);
- MailSite ms = new MailSite(accprops);
- ms.Publish();
-
this.mb = new MessageBank(accdir.getName());
File nimdir = new File(contacts_dir, AccountManager.NIMDIR);
@@ -36,8 +35,9 @@
this.nf = null;
}
- this.rtsf = new RTSFetcher("KSK@"+accprops.get("rtskey")+"-", inbound_dir, accdir);
+ this.rtsf = new RTSFetcher("KSK@"+this.accprops.get("rtskey")+"-", inbound_dir, accdir);
+
//this.mf = new MailFetcher(this.mb, inbound_dir, Freemail.getFCPConnection());
}
@@ -45,6 +45,13 @@
while (true) {
long start = System.currentTimeMillis();
+ if (System.currentTimeMillis() > this.mailsite_last_upload + MAILSITE_UPLOAD_INTERVAL) {
+ MailSite ms = new MailSite(this.accprops);
+ if (ms.Publish() > 0) {
+ this.mailsite_last_upload = System.currentTimeMillis();
+ }
+ }
+
if (this.nf != null) {
nf.fetch();
}
Modified: trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java
===================================================================
--- trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java 2006-07-23 15:50:59 UTC (rev 9735)
+++ trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java 2006-07-23 17:27:55 UTC (rev 9736)
@@ -145,7 +145,7 @@
return -1;
}
if (emsg == null) {
- System.out.println("insert successful");
+ System.out.println("insert of "+basekey+"-"+slot+suffix+" successful");
return slot;
} else if (emsg.errorcode == FCPInsertErrorMessage.COLLISION) {
slot++;
@@ -175,7 +175,7 @@
return -1;
}
if (emsg == null) {
- System.out.println("insert successful");
+ System.out.println("insert of "+basekey+"-"+slot+suffix+" successful");
return slot;
} else if (emsg.errorcode == FCPInsertErrorMessage.COLLISION) {
slot++;
From dbkr at freenetproject.org Mon Jul 24 19:50:48 2006
From: dbkr at freenetproject.org (dbkr at freenetproject.org)
Date: Mon, 24 Jul 2006 19:50:48 +0000 (UTC)
Subject: [Freemail] r9741 - trunk/apps/Freemail/docs/spec
Message-ID: <20060724195048.5D13A9C757@emu.freenetproject.org>
Author: dbkr
Date: 2006-07-24 19:50:45 +0000 (Mon, 24 Jul 2006)
New Revision: 9741
Modified:
trunk/apps/Freemail/docs/spec/spec.tex
Log:
Formatting and spelling corrections on spec doc.
Modified: trunk/apps/Freemail/docs/spec/spec.tex
===================================================================
--- trunk/apps/Freemail/docs/spec/spec.tex 2006-07-23 21:18:05 UTC (rev 9740)
+++ trunk/apps/Freemail/docs/spec/spec.tex 2006-07-24 19:50:45 UTC (rev 9741)
@@ -4,11 +4,11 @@
\date{July 2006}
\maketitle
-This is a working draft of the Freemail spcification. All parts of this document are subject to change.
+This is a working draft of the Freemail specification. All parts of this document are subject to change.
\section{Introduction}
\subsection{What is Freemail}
-Freemail is an email-like messaging system that transports all messages over Freenet 0.7 in order to achieve anonymity and cencorship-resillience. Its protocol is designed to be