Added RFC linked to: DK, DKIM, OpenPGP (unable to understand S/Mime, i'll try again later)

Next Time, i'll learn to <ctrl>+s

Change Done on HeaderSet (added ListAll)
And changed way to merge multiple headers with the same name

Started DKIM work, i'll need to expose various stuff

So, the DKIM Infrastructure should be alright...

(Or it's just a joke and it will wipe your hd)

Yipeee, DKIM Signer theorically Done.

Nope, just a joke.

Should be OK this time, the new protected functions are not moved with protected functions for now to ease the merge

Done with DKIM Needs: test-cases

Corrected CodeStyle Added License

Various changes (i know, should be in small commits, but they are pretty grouped here)

[DKIM] Test Cases + Debug

Added Some test Cases to track major regressions

Keys will NEVER BE used online and should not be used

[CLEANUP] Delete old keys i was not even aware were still there

Deleted Dummy Key Cache to only commit usefull files

[DKIM] Corrected a bug the SHA256-Signing was using sha1

[DKIM] - Debug Removed trailing space in signature, Bug Fix in header order
This allows swiftmailer to pass simple/simple canonicalisation.
The header order will render the dkim less error prone.

[DKIM] Debug on trailing Line Feed for signature

+ Added DomainKey-Signature Header Ordering

[DomainKeys] Initial Checkin

Added DomainKey-Signer

[TYPOS] Updated Doc to hide copy/paste

Erased last occurences of DKIM
added S/MIME Signer and Encryption support
Fixed missing static keyword
[Signers] Allow using an array of certificates for SMimeSigner#setEncryptCertificate()
fixed CS
[Signer] added testing for s/mime encrypted message with multiple certificates
[Signers] fixed testing code, testEncryptThenSignMessage was not fully executed
merged branch sstok/smime (PR #227)

This PR was merged into the master branch.

Commits
-------

0e8d0d4 [Signers] fixed testing code, testEncryptThenSignMessage was not fully executed
6bdb620 [Signer] added testing for s/mime encrypted message with multiple certificates
fbaa801 fixed CS
b647fd4 [Signers] Allow using an array of certificates for SMimeSigner#setEncryptCertificate()
0e2f99a Fixed missing static keyword
fc649a0 added S/MIME Signer and Encryption support
912cdf1 Added RFC linked to: DK, DKIM, OpenPGP (unable to understand S/Mime, i'll try again later)

Discussion
----------

S/MIME Signer and Encryption support

This adds the S/MIME Signer for signing and encrypting messages.
It largely includes the work done by Xavier De Cock (original signer implementation) and @Romain-Geissler.

Related to: #11

---------------------------------------------------------------------------

by xdecock at 2012-07-05T19:07:42Z

Hi, have not yet been able to test, but is my code as buggy as the list
seems to tell? i need to find a few hours to test and fix it

On Thu, Jul 5, 2012 at 4:08 PM, Sebastiaan Stok <
reply@reply.github.com
> wrote:

> This adds the S/MIME Signer for signing and encrypting messages.
> It largely includes the work done by Xavier De Cock (original signer
> implementation) and @Romain-Geissler.
>
> Its still a work in progress, as I still need to test it and clean-up.
>
> Related to: #11
>
> ---
> Reply to this email directly or view it on GitHub:
> https://github.com/swiftmailer/swiftmailer/issues/227
>

--
Xavier De Cock
GPG Fingerprint: 93CA EE3F 9F57 5BE1 AE4A  794D 3C74 CA9E E7A5 0C1B
GPG Id: 0xE7A50C1B

---------------------------------------------------------------------------

by sstok at 2012-07-06T07:54:14Z

@xdecock What do you mean with messy? The header signing code is something that is not really clear and should be re-factored IMO.

I changed the coding style as we now use PSR-2
And loop performing the signing, as you where performing the loop twice for all types even tho there is only body signer and one header signer ;)

I still have to push my latest changes as this current version will crash in recursion.

---------------------------------------------------------------------------

by xdecock at 2012-07-06T09:53:07Z

It's a code i haven't checked for 3 years or so,

but the testers are saying it does not work and signatures are considered
invalid,

but i need to check all those classes, basically, i'll check all this when
you have a stable code, re-read my  hash calculation, and refactor the
header signing :)

Xavier.

On Fri, Jul 6, 2012 at 9:54 AM, Sebastiaan Stok <
reply@reply.github.com
> wrote:

> @xdecock What do you mean with messy? The header signing code is something
> that is not really clear and should be re-factored IMO.
>
> I changed the coding style as we now use PSR-2
> And loop performing the signing, as you where performing the loop twice
> for all types even tho there is only body signer and one header signer ;)
>
> I still have to push my latest changes as this current version will crash
> in recursion.
>
> ---
> Reply to this email directly or view it on GitHub:
> https://github.com/swiftmailer/swiftmailer/pull/227#issuecomment-6799300
>

--
Xavier De Cock
GPG Fingerprint: 93CA EE3F 9F57 5BE1 AE4A  794D 3C74 CA9E E7A5 0C1B
GPG Id: 0xE7A50C1B

---------------------------------------------------------------------------

by sstok at 2012-07-06T13:21:31Z

The good news I got the S/MIME signer working, at least the result looks good.
Testing this is a challenge as I need to make sure everything is conforming the specs.

---------------------------------------------------------------------------

by sstok at 2012-07-07T13:17:37Z

I got the detached (mutipart) working, encrypted keeps giving "error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag" Which basically means that something is going wrong with the content.

Hopefully I fix this today, else its gonna be Monday.

Edit: Why is it always when I post that something is not working I find the solution!
I forgot to reset the read-pointer.

---------------------------------------------------------------------------

by sstok at 2012-07-07T14:38:00Z

The basis tests are done. Only need to perform some testing with attachments.

Then its ready for final review :warning: :ok:

---------------------------------------------------------------------------

by sstok at 2012-07-08T11:01:44Z

@fabpot ping

---------------------------------------------------------------------------

by sstok at 2012-07-12T15:14:00Z

OK... looks like I mest-up my branch (good thing I made a back-up), can anyone please tell how to properly apply a rebase??

I did this.

```
$ git checkout master
$ git fetch upstream
$ git merge upstream/master
$ git checkout smime
$ git rebase master
```

And got many conflicts that I resolved using 'Theirs' and finally got everything up-to-date but can no longer squash as my commits are before others.

---------------------------------------------------------------------------

by Romain-Geissler at 2012-07-12T15:27:18Z

Hi,

What did you do exactly? Do still have a branch where with this PR (without any other messy commits?). Is there is the current messy branch some commits you want to keep but are not in your backup branch?

If you messed your current branch in one go (or a small number of step that you know), then the reflog might be helpful (see if ``git log smime@{1}`` looks good)

---------------------------------------------------------------------------

by sstok at 2012-07-12T18:04:40Z

I figured need to only use 'git rebase master', and not the git merge
part.

I have not performed this before and my back-up branch is not not
rebased so I hope it works else I will reopen en new pull request :)

On 12.07.2012 17:27, Romain Geissler wrote:
> Hi,
>
> What did you do exactly? Do still have a branch where with this PR
> (without any other messy commits?). Is there is the current messy
> branch some commits you want to keep but are not in your backup
> branch?
>
> If you messed your current branch in one go (or a small number of
> step that you know), then the reflog might be helpful (see if ``git
> smime@{1}``)
>
> ---
> Reply to this email directly or view it on GitHub:
>
> https://github.com/swiftmailer/swiftmailer/pull/227#issuecomment-6938283

---------------------------------------------------------------------------

by Romain-Geissler at 2012-07-12T20:05:46Z

Well your current pull request is still messy as it embeds some commits already pushed to the main branch.

Before doing anything, I strongly suggest you keep  a copy of your ``smime`` branch somewhere (but keep in mind that the reflog has also been created for this purpose):

```sh
git branch smime-pr-227-backup smime
```

Now lets move to a new branch, pointing to the commit prior to your current PR:

```sh
git checkout -b clean-smime-pr-227 6c867cb~
```

Now we simply add all commits from the messy branch, in that order, filtering by commit authors (xdecock and you) :

```sh
git rev-list -E --author='xdecock|stok' 6c867cb~..smime|git cherry-pick --stdin
```

You'll have to resolve some conflict, like when rebasing. When resolved, run ``git add`` to stage the conflicting files, then continue with ``git cherry-pick --continue``.

Finally, you can replace the old messy ``smime`` branch by the clean new one (that is the destructive part of the process, but hopefully you did back the ``smime`` branch at the beginning) :

```sh
git checkout smime
git reset --hard clean-smime-pr-227
```

Finally, if you are sure of what you did, you can update the github pull request by pushing to your github fork (again, this is a destructive part, as the old advertised PR will be replaced by the new clean one).

```sh
git push -f my_github_remote_name smime:smime
```

PS: you will gain real potential by learning how to really use git.

---------------------------------------------------------------------------

by sstok at 2012-07-13T08:27:24Z

Sweet!!! It worked! Now to squash my commits.

---------------------------------------------------------------------------

by sstok at 2012-07-13T09:30:43Z

Its a good thing git is open-source and consists of many Shell files :) because I needed to modify git-rebase--interactive to keep my authorship.

Great, now there it an exception I need to fix !! :D
Test cases run: 104/104, Passes: 3674, Failures: 0, Exceptions: 1

---------------------------------------------------------------------------

by Romain-Geissler at 2012-07-13T09:38:57Z

git-rebase always keep the commit authorship, even when editing existing commits (amending) except when you merge several commit in one (squash or fixup): the base commit author is kept, amend commit's authors are lost.

---------------------------------------------------------------------------

by sstok at 2012-07-13T09:44:47Z

Yes I know, I meant the final squashed version.

After squashing, the squashed versions contained the authorship of the first commit, which was xavier.
http://marc.info/?l=git&m=119110899630824

The exception was due to a not up-to-date branch. one final squash and push, and I'm finally done...

---------------------------------------------------------------------------

by stof at 2012-07-13T12:42:59Z

@sstok but as your work include the work done by Xavier, he lost authorship because of your squash. You should have squashed Xavier's commit together and then your commits together, keeping 2 commits to avoid removing the authorship.

---------------------------------------------------------------------------

by sstok at 2012-07-13T14:24:11Z

Will do that tomorrow.

And the author is still mentioned in the source code ;)

---------------------------------------------------------------------------

by stof at 2012-07-13T18:59:05Z

Well, mentioning in the source does not give the authorship on the changes he did. Such authorship is available through the git history.

---------------------------------------------------------------------------

by sstok at 2012-07-14T08:51:50Z

OK, it should be good now.

I previous removed the DKIM/DomainKeys singing code as it was unrelated to my pull request but reverted that now.
The tests pass but it should be looked at as its very old.

One thing I'm concerned about is the LGPL licence, Domain Keys has various patents.
https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail#Patent_encumbrance

And IIRC (L)GPL has some problems with that, I can be wrong but not jurist :)

---------------------------------------------------------------------------

by sstok at 2012-07-14T10:12:10Z

OK, one more time... then I'm gonna kill my self :D
The CS is still not fixed. working on it.. I'd disable whitespace comparison for faster view. so I missed these changes.

---------------------------------------------------------------------------

by sstok at 2012-07-14T10:47:36Z

OK, take (I lost count). the CS is fixed, line wrapping in documentation seem correct and all tests pass.
If everything is good now I will squash my last commits and this can be merged.

---------------------------------------------------------------------------

by sstok at 2012-07-19T09:50:36Z

@stof ping

---------------------------------------------------------------------------

by Romain-Geissler at 2012-07-24T14:35:12Z

Hi,

I'm using your branch for one of my project. At first glance it seems to work well.

Please note that the encryption certificate can in fact be an array of certificates. Indeed, you might send an encrypted certificate to several recepients at once. The message is then encrypted several time, once for each certificate provided (each recepient have one certificate). Instead of sending several small messages with one recepient, a big one is sent with the original message being encrypted several times (that's defined by the SMIME standard). So please consider refactoring your class to accept an array of encryption certificates.

And here is a little fixup for you (forgot the "static" qualifier):

```diff
diff --git a/lib/classes/Swift/Signers/SMimeSigner.php b/lib/classes/Swift/Signers/SMimeSigner.php
index 99d5f18..4f22cda 100644
--- a/lib/classes/Swift/Signers/SMimeSigner.php
+++ b/lib/classes/Swift/Signers/SMimeSigner.php
@@ -77,7 +77,7 @@ class Swift_Signers_SMimeSigner implements Swift_Signers_BodySigner
      *
      * @return Swift_Signers_SMimeSigner
      */
-    public function newInstance($certificate = null, $privateKey = null)
+    public static function newInstance($certificate = null, $privateKey = null)
     {
         return new static($certificate, $privateKey);
     }
```

Hope that @fabpot will merge this, one day... SMIME is a very important part of mails when you're dealing with confidentiality and authentication.

---------------------------------------------------------------------------

by sstok at 2012-07-25T07:57:27Z

@Romain-Geissler Good to hear!

Can you point to the exact section in RFC of S/MIME?
Or give can you give an example on how tho implement this.

---------------------------------------------------------------------------

by Romain-Geissler at 2012-07-25T09:15:13Z

Well i made a little mistake when saying that the message was encrypted once for each recipient. It's much more clever than that, to avoid linear data growth with the number of recipient.

In fact, the message is encrypted only once, using a random generated symmetric key, then this symmetric key is encrypted once with each recipient private key. Thus the overhead of encrypting an original message, no matter it's a 8 bytes or a 10 MB message, is the same in all cases, for a given number of recipient.

Quote from [RFC 5751 (S/MIME 3.2)](http://tools.ietf.org/html/rfc5751)

Step 2 is the one that explains the multiple recipient concerns.

>3.3.  Creating an Enveloped-Only Message
>
>   This section describes the format for enveloping a MIME entity
>   without signing it.  It is important to note that sending enveloped
>   but not signed messages does not provide for data integrity.  It is
>   possible to replace ciphertext in such a way that the processed
>   message will still be valid, but the meaning can be altered.
>
>   Step 1.  The MIME entity to be enveloped is prepared according to
>            Section 3.1.
>
>   Step 2.  The MIME entity and other required data is processed into a
>            CMS object of type EnvelopedData.  In addition to encrypting
>            a copy of the content-encryption key for each recipient, a
>            copy of the content-encryption key SHOULD be encrypted for
>            the originator and included in the EnvelopedData (see [CMS],
>            Section 6).
>
>   Step 3.  The EnvelopedData object is wrapped in a CMS ContentInfo
>            object.
>
>   Step 4.  The ContentInfo object is inserted into an
>            application/pkcs7-mime MIME entity.
>
>   The smime-type parameter for enveloped-only messages is "enveloped-
>   data".  The file extension for this type of message is ".p7m".

Quote from [RFC 5652 (CMS)](http://tools.ietf.org/html/rfc5652). Again, step 2 is the one we are interested in:

> 6.  Enveloped-data Content Type
>
>   The enveloped-data content type consists of an encrypted content of
>   any type and encrypted content-encryption keys for one or more
>   recipients.  The combination of the encrypted content and one
>   encrypted content-encryption key for a recipient is a "digital
>   envelope" for that recipient.  Any type of content can be enveloped
>   for an arbitrary number of recipients using any of the supported key
>   management techniques for each recipient.
>
>   The typical application of the enveloped-data content type will
>   represent one or more recipients' digital envelopes on content of the
>   data or signed-data content types.
>
>   Enveloped-data is constructed by the following steps:
>
>   1.  A content-encryption key for a particular content-encryption
>       algorithm is generated at random.
>
>   2.  The content-encryption key is encrypted for each recipient.  The
>       details of this encryption depend on the key management algorithm
>       used, but four general techniques are supported:
>
>         key transport:  the content-encryption key is encrypted in the
>         recipient's public key;
>
>         key agreement:  the recipient's public key and the sender's
>         private key are used to generate a pairwise symmetric key, then
>         the content-encryption key is encrypted in the pairwise
>         symmetric key;
>
>         symmetric key-encryption keys:  the content-encryption key is
>         encrypted in a previously distributed symmetric key-encryption
>         key; and
>
>         passwords: the content-encryption key is encrypted in a key-
>         encryption key that is derived from a password or other shared
>         secret value.
>
>   3.  For each recipient, the encrypted content-encryption key and
>       other recipient-specific information are collected into a
>       RecipientInfo value, defined in Section 6.2.
>
>   4.  The content is encrypted with the content-encryption key.
>       Content encryption may require that the content be padded to a
>       multiple of some block size; see Section 6.3.
>
>   5.  The RecipientInfo values for all the recipients are collected
>       together with the encrypted content to form an EnvelopedData
>       value as defined in Section 6.1.
>
>   A recipient opens the digital envelope by decrypting one of the
>   encrypted content-encryption keys and then decrypting the encrypted
>   content with the recovered content-encryption key.
>
>   This section is divided into four parts.  The first part describes
>   the top-level type EnvelopedData, the second part describes the per-
>   recipient information type RecipientInfo, and the third and fourth
>   parts describe the content-encryption and key-encryption processes.

For implementation, that's not quite difficult. ```openssl_pkcs7_encrypt``` accepts both a single certificate or an array of certificates. IIRC, my original implementation that inspired you required the ```recipientCertificates``` parameter to be an array. You just need to allow arrays in your setter.

---------------------------------------------------------------------------

by sstok at 2012-07-25T14:39:26Z

No problem, I'm not able to write a test for it now (this stupid heat is killing me), but it should be good.

---------------------------------------------------------------------------

by sstok at 2012-08-08T08:54:50Z

@Romain-Geissler Should be good now, can you check.

---------------------------------------------------------------------------

by Romain-Geissler at 2012-08-08T13:48:04Z

@sstok I successfully deployed the latest ``smime`` branch and it seems to work as before : a simple mail, without body but with one attachment, signed then encrypted (with only one encryption certificate) that i can correctly read using Apple Mail client. Your changes to allow multiple encryption certificate seems to be ok.

@fabpot This PR should definitely be considered for a merge.

---------------------------------------------------------------------------

by fabpot at 2012-08-10T14:19:33Z

@xdecock Can you review the code now that it is finished? Thanks.

---------------------------------------------------------------------------

by xdecock at 2012-08-10T14:54:06Z

@fabpot, will do this tomorrow or next week, i'll let know

xavier

On Fri, Aug 10, 2012 at 4:19 PM, Fabien Potencier
<notifications@github.com>wrote:

> @xdecock <https://github.com/xdecock> Can you review the code now that it
> is finished? Thanks.
>
> —
> Reply to this email directly or view it on GitHub<https://github.com/swiftmailer/swiftmailer/pull/227#issuecomment-7645794>.
>
>

--
Xavier De Cock
GPG Fingerprint: 93CA EE3F 9F57 5BE1 AE4A  794D 3C74 CA9E E7A5 0C1B
GPG Id: 0xE7A50C1B
fixed CS
updated CHANGES