1 // Copyright 2000-2008 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
6 import org.ibex.crypto.*;
8 import org.ibex.util.*;
9 import org.ibex.mail.protocol.*;
14 // http://cr.yp.to/proto/verp.txt
17 private static final Random random = new Random();
19 public static Address verpSign(Address a, byte[] secret) {
20 return verpSign(a, secret, System.currentTimeMillis());
24 // VERP--<when>-<salt>-<sig>-<user>@domain.com
25 // <when> = 64-bit hexadecimal integer
26 // <salt> = 16-bit hexadecimal integer
27 // <user> = original username (ie local-part)
28 // <sig> = base64(sha1(VERP--<when>-<salt>-<user><secret>))
29 /** converts an Address into a VERP-signed address with signature time "when" and extra payload "extra" */
30 public static Address verpSign(Address a, byte[] secret, long when) {
31 if (a.user==null || "".equals(a.user)) {
32 Log.warn(VERP.class, "note: not VERP-signing the null address: "+a);
36 int salt = Math.abs(random.nextInt()) & 0xffff;
38 StringBuffer ret = new StringBuffer();
40 ret.append(Long.toString(when, 16));
42 ret.append(Integer.toString(salt, 16));
45 byte[] b = (ret.toString()+a.user).getBytes();
46 SHA1 sha1 = new SHA1();
47 sha1.update(b, 0, b.length);
48 sha1.update(secret, 0, secret.length);
49 b = new byte[sha1.getDigestSize()];
52 ret.append(new String(Encode.toBase64(b)));
55 // FIXME: encode a.host in here
56 return new Address(ret.toString(), SMTP.localHostIsMXFor, a.description);
59 // FIXME: return unverpified address
60 /** returns the field passed as "extra" when signing, or null if signature invalid */
61 public static String verpVerify(Address a, byte[] secret, long noEarlierThan) {
64 i = s.indexOf("--", i); if (i==-1) return null; i += 2;
66 i = s.indexOf('-', i); if (i==-1) return null; i++;
68 i = s.indexOf('-', i); if (i==-1) return null; i++;
70 i = s.indexOf('-', i); if (i==-1) return null; i++;
72 String verify = s.substring(0,third)+s.substring(fourth);
73 Log.error("VERP", "verify=\""+verify+"\"");
75 byte[] b = verify.getBytes();
76 SHA1 sha1 = new SHA1();
77 sha1.update(b, 0, b.length);
78 sha1.update(secret, 0, secret.length);
79 b = new byte[sha1.getDigestSize()];
81 if (!new String(Encode.toBase64(b)).equals(s.substring(third,fourth-1))) {
82 Log.error("VERP", "decrypt failed\n"+new String(Encode.toBase64(b))+"\n"+s.substring(third,fourth-1));
85 // FIXME: check the host on the address
86 long when = Long.parseLong(s.substring(first, second-1), 16);
87 Log.error("VERP", "when="+when);
88 if (when < noEarlierThan) return null;
89 return s.substring(fourth);