1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.jdkim;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.IOException;
24  import java.security.NoSuchAlgorithmException;
25  import java.security.PrivateKey;
26  import java.security.interfaces.RSAKey;
27  import java.security.spec.InvalidKeySpecException;
28  import java.util.List;
29  import java.util.Properties;
30  
31  import javax.mail.Address;
32  import javax.mail.MessagingException;
33  import javax.mail.Session;
34  import javax.mail.Transport;
35  import javax.mail.internet.InternetAddress;
36  import javax.mail.internet.MimeMessage;
37  
38  import junit.framework.TestCase;
39  
40  import org.apache.james.jdkim.api.PublicKeyRecord;
41  import org.apache.james.jdkim.api.PublicKeyRecordRetriever;
42  import org.apache.james.jdkim.exceptions.FailException;
43  import org.apache.james.jdkim.exceptions.PermFailException;
44  import org.apache.james.jdkim.exceptions.TempFailException;
45  import org.apache.james.jdkim.impl.DNSPublicKeyRecordRetriever;
46  import org.apache.james.jdkim.tagvalue.SignatureRecordImpl;
47  import org.apache.james.jdkim.tagvalue.TagValue;
48  import org.apache.mailet.HostAddress;
49  
50  import com.sun.mail.smtp.SMTPTransport;
51  
52  public class DNSPublicKeyRetrieverTest extends TestCase {
53  
54      public void testWrongOption() throws TempFailException {
55          try {
56              new DNSPublicKeyRecordRetriever().getRecords("somethingelse",
57                      "test", "test");
58              fail("expected unsupported operation");
59          } catch (PermFailException e) {
60              e.printStackTrace();
61          }
62      }
63  
64      public void testConstructor() {
65          new DNSPublicKeyRecordRetriever();
66      }
67  
68      /**
69       * TODO: Requires internet connection
70       * 
71       * @throws PermFailException
72       */
73      public void testRetrieve() throws TempFailException, PermFailException {
74          PublicKeyRecordRetriever pkr = new DNSPublicKeyRecordRetriever();
75          System.out.println(pkr.getRecords("dns/txt", "beta", "gmail.com"));
76          System.out
77                  .println(pkr.getRecords("dns/txt", "lima", "yahoogroups.com"));
78  
79          new TagValue((String) pkr.getRecords("dns/txt", "lima",
80                  "yahoogroups.com").get(0));
81      }
82  
83      public void testKeyPair() throws PermFailException, TempFailException,
84              NoSuchAlgorithmException, InvalidKeySpecException {
85          PublicKeyRecord key = new DKIMVerifier()
86                  .publicKeySelector(new MockPublicKeyRecordRetriever(
87                          "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQAB;",
88                          "dummy", "dummy").getRecords("dns/txt", "dummy",
89                          "dummy"));
90  
91          // String privateKey =
92          // "MIICXAIBAAKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQABAoGBAI8XcwnZi0Sq5N89wF+gFNhnREFo3rsJDaCY8iqHdA5DDlnr3abb/yhipw0I/1HlgC6fIG2oexXOXFWl+USgqRt1kTt9jXhVFExg8mNko2UelAwFtsl8CRjVcYQOcedeH/WM/mXjg2wUqqZenBmlKlD6vNb70jFJeVaDJ/7n7j8BAkEA9NkH2D4Zgj/IOAVYccZYH74+VgO0e7VkUjQk9wtJ2j6cGqJ6Pfj0roVIMUWzoBb8YfErR8l6JnVQbfy83gJeiQJBAOHk3ow7JjAn8XuOyZx24KcTaYWKUkAQfRWYDFFOYQF4KV9xLSEtycY0kjsdxGKDudWcsATllFzXDCQF6DTNIWECQEA52ePwTjKrVnLTfCLEG4OgHKvlZud4amthwDyJWoMEH2ChNB2je1N4JLrABOE+hk+OuoKnKAKEjWd8f3Jg/rkCQHj8mQmogHqYWikgP/FSZl518jV48Tao3iXbqvU9Mo2T6yzYNCCqIoDLFWseNVnCTZ0Qb+IfiEf1UeZVV5o4J+ECQDatNnS3V9qYUKjj/krNRD/U0+7eh8S2ylLqD3RlSn9KtYGRMgAtUXtiOEizBH6bd/orzI9V9sw8yBz+ZqIH25Q=";
93          String privateKeyPKCS8 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANgNpgpfPBVjCpZsuGa4nrppMA3zCYNH6t8cTwd+eRI5rHSgihMznOq5mtMujfTzvRgx9jPHB8HqP83PdB3CtQP+3RgxgmJQrJYmcIp9lcckEn7J9Eevuhb5RbdxWj0IbZsF8jGwifBh7XvmD1SPKe0mla56p0QijVzZuG/0ynrpAgMBAAECgYEAjxdzCdmLRKrk3z3AX6AU2GdEQWjeuwkNoJjyKod0DkMOWevdptv/KGKnDQj/UeWALp8gbah7Fc5cVaX5RKCpG3WRO32NeFUUTGDyY2SjZR6UDAW2yXwJGNVxhA5x514f9Yz+ZeODbBSqpl6cGaUqUPq81vvSMUl5VoMn/ufuPwECQQD02QfYPhmCP8g4BVhxxlgfvj5WA7R7tWRSNCT3C0naPpwaono9+PSuhUgxRbOgFvxh8StHyXomdVBt/LzeAl6JAkEA4eTejDsmMCfxe47JnHbgpxNphYpSQBB9FZgMUU5hAXgpX3EtIS3JxjSSOx3EYoO51ZywBOWUXNcMJAXoNM0hYQJAQDnZ4/BOMqtWctN8IsQbg6Acq+Vm53hqa2HAPIlagwQfYKE0HaN7U3gkusAE4T6GT466gqcoAoSNZ3x/cmD+uQJAePyZCaiAephaKSA/8VJmXnXyNXjxNqjeJduq9T0yjZPrLNg0IKoigMsVax41WcJNnRBv4h+IR/VR5lVXmjgn4QJANq02dLdX2phQqOP+Ss1EP9TT7t6HxLbKUuoPdGVKf0q1gZEyAC1Re2I4SLMEfpt3+ivMj1X2zDzIHP5mogfblA==";
94  
95          PrivateKey privKey = DKIMSigner.getPrivateKey(privateKeyPKCS8);
96  
97          // controllo che il modulus della chiave privata corrisponda al record
98          // pubblico
99          assertEquals(((RSAKey) privKey).getModulus(), ((RSAKey) key
100                 .getPublicKey()).getModulus());
101     }
102 
103     public void testSignVerify() throws NoSuchAlgorithmException,
104             InvalidKeySpecException, IOException, FailException {
105         MockPublicKeyRecordRetriever mockPublicKeyRecordRetriever = new MockPublicKeyRecordRetriever(
106                 "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQAB;",
107                 "selector", "example.com");
108         PublicKeyRecord key = new DKIMVerifier()
109                 .publicKeySelector(mockPublicKeyRecordRetriever.getRecords(
110                         "dns/txt", "selector", "example.com"));
111         String privateKeyPKCS8 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANgNpgpfPBVjCpZsuGa4nrppMA3zCYNH6t8cTwd+eRI5rHSgihMznOq5mtMujfTzvRgx9jPHB8HqP83PdB3CtQP+3RgxgmJQrJYmcIp9lcckEn7J9Eevuhb5RbdxWj0IbZsF8jGwifBh7XvmD1SPKe0mla56p0QijVzZuG/0ynrpAgMBAAECgYEAjxdzCdmLRKrk3z3AX6AU2GdEQWjeuwkNoJjyKod0DkMOWevdptv/KGKnDQj/UeWALp8gbah7Fc5cVaX5RKCpG3WRO32NeFUUTGDyY2SjZR6UDAW2yXwJGNVxhA5x514f9Yz+ZeODbBSqpl6cGaUqUPq81vvSMUl5VoMn/ufuPwECQQD02QfYPhmCP8g4BVhxxlgfvj5WA7R7tWRSNCT3C0naPpwaono9+PSuhUgxRbOgFvxh8StHyXomdVBt/LzeAl6JAkEA4eTejDsmMCfxe47JnHbgpxNphYpSQBB9FZgMUU5hAXgpX3EtIS3JxjSSOx3EYoO51ZywBOWUXNcMJAXoNM0hYQJAQDnZ4/BOMqtWctN8IsQbg6Acq+Vm53hqa2HAPIlagwQfYKE0HaN7U3gkusAE4T6GT466gqcoAoSNZ3x/cmD+uQJAePyZCaiAephaKSA/8VJmXnXyNXjxNqjeJduq9T0yjZPrLNg0IKoigMsVax41WcJNnRBv4h+IR/VR5lVXmjgn4QJANq02dLdX2phQqOP+Ss1EP9TT7t6HxLbKUuoPdGVKf0q1gZEyAC1Re2I4SLMEfpt3+ivMj1X2zDzIHP5mogfblA==";
112         PrivateKey privKey = DKIMSigner.getPrivateKey(privateKeyPKCS8);
113 
114         // Check that the private key modulus equals the public key modulus
115         assertEquals(((RSAKey) privKey).getModulus(), ((RSAKey) key
116                 .getPublicKey()).getModulus());
117 
118         DKIMSigner signer = new DKIMSigner(
119                 "v=1; s=selector; d=example.com; h=from:to; a=rsa-sha256; bh=; b=;",
120                 privKey);
121         String message = "From: io@bago.org\r\nTo: io@bago.org\r\n\r\nbody\r\n";
122         String res = signer.sign(new ByteArrayInputStream(message.getBytes()));
123         System.out.println(res);
124         String signedMessage = res + "\r\n"
125                 + "From: io@bago.org\r\nTo: io@bago.org\r\n\r\nbody\r\n";
126 
127         new DKIMVerifier(mockPublicKeyRecordRetriever)
128                 .verify(new ByteArrayInputStream(signedMessage.getBytes()));
129 
130     }
131 
132     /*
133      * public void testDONOTCOMMITME() throws NoSuchAlgorithmException,
134      * InvalidKeySpecException, IOException, FailException, MessagingException {
135      * List records = new DNSPublicKeyRecordRetriever().getRecords("dns/txt",
136      * "selector1", "emailsimulator.com"); PublicKeyRecord key = new
137      * DKIMVerifier().publicKeySelector(records);
138      * System.out.println(key.toString()); key.validate(); String
139      * privateKeyPKCS8 =
140      * "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANgNpgpfPBVjCpZsuGa4nrppMA3zCYNH6t8cTwd+eRI5rHSgihMznOq5mtMujfTzvRgx9jPHB8HqP83PdB3CtQP+3RgxgmJQrJYmcIp9lcckEn7J9Eevuhb5RbdxWj0IbZsF8jGwifBh7XvmD1SPKe0mla56p0QijVzZuG/0ynrpAgMBAAECgYEAjxdzCdmLRKrk3z3AX6AU2GdEQWjeuwkNoJjyKod0DkMOWevdptv/KGKnDQj/UeWALp8gbah7Fc5cVaX5RKCpG3WRO32NeFUUTGDyY2SjZR6UDAW2yXwJGNVxhA5x514f9Yz+ZeODbBSqpl6cGaUqUPq81vvSMUl5VoMn/ufuPwECQQD02QfYPhmCP8g4BVhxxlgfvj5WA7R7tWRSNCT3C0naPpwaono9+PSuhUgxRbOgFvxh8StHyXomdVBt/LzeAl6JAkEA4eTejDsmMCfxe47JnHbgpxNphYpSQBB9FZgMUU5hAXgpX3EtIS3JxjSSOx3EYoO51ZywBOWUXNcMJAXoNM0hYQJAQDnZ4/BOMqtWctN8IsQbg6Acq+Vm53hqa2HAPIlagwQfYKE0HaN7U3gkusAE4T6GT466gqcoAoSNZ3x/cmD+uQJAePyZCaiAephaKSA/8VJmXnXyNXjxNqjeJduq9T0yjZPrLNg0IKoigMsVax41WcJNnRBv4h+IR/VR5lVXmjgn4QJANq02dLdX2phQqOP+Ss1EP9TT7t6HxLbKUuoPdGVKf0q1gZEyAC1Re2I4SLMEfpt3+ivMj1X2zDzIHP5mogfblA==";
141      * PrivateKey privKey = DKIMSigner.getPrivateKey(privateKeyPKCS8);
142      *  // Check that the private key modulus equals the public key modulus
143      * assertEquals(((RSAKey) privKey).getModulus(), ((RSAKey)
144      * key.getPublicKey()).getModulus());
145      *  // NOTE: this works both with "b=;" and "b=" but not with WSP/FWS after
146      * the b=". DKIMSigner signer = new DKIMSigner("v=1; c=simple/simple;
147      * s=selector1; d=emailsimulator.com; h=from:to:message-id:date; a=rsa-sha1;
148      * bh=; b=;", privKey); String message ="Date: Thu, 1 Oct 2009 17:15:28
149      * +0200 (CEST)\r\nFrom: <io@bago.org>\r\nMessage-Id:
150      * <test4325223452@localhost>\r\nSubject: prova11 bago.org\r\nTo:
151      * <vidocq@gmail.com>\r\n\r\nbody text\r\n"; String res = signer.sign(new
152      * ByteArrayInputStream(message.getBytes())); System.out.println(res);
153      * String signedMessage =res+"\r\n"+message;
154      * 
155      * new DKIMVerifier().verify(new
156      * ByteArrayInputStream(signedMessage.getBytes()));
157      * 
158      * System.out.println("-------------------------"); Properties props = new
159      * Properties(); props.put("mail.smtp.from", "io@bago.org"); Session session =
160      * Session.getDefaultInstance(props); MimeMessage m = new
161      * MimeMessage(session, new ByteArrayInputStream(signedMessage.getBytes()));
162      * m.writeTo(System.out);
163      * 
164      * HostAddress ha = new HostAddress("vm3.void.it", "smtp://94.23.67.198");
165      * Transport transport = session.getTransport(ha);
166      * transport.connect("vm3.void.it", 6025, "bago", "bv678nt"); Address[]
167      * recipients = new Address[] { new InternetAddress("vidocq@gmail.com"), new
168      * InternetAddress("bago@ngi.it") }; transport.sendMessage(m, recipients);
169      * transport.close();
170      *  }
171      */
172 
173 }