001 package edu.harvard.deas.hyperenc; 002 003 import java.io.Serializable; 004 import java.util.ArrayList; 005 import java.util.Date; 006 import java.util.List; 007 008 /** 009 * A HyperMessage is a hyper-encrypted message sent from one HyperEncryption 010 * client to another. It encompasses reconciliation and other protocol messages, 011 * as well as actual encrypted messages containing user-specified content. 012 * <p> 013 * A HyperMessage has several abstract fields: 014 * <ul> 015 * <li><i>id</i> - a unique ID number assigned to each HyperMessage</li> 016 * <li><i>sender</i> - the person who sent the message</li> 017 * <li><i>recipient</i> - the person to whom the message is addressed</li> 018 * <li><i>type</i> - what type of message this is: whether it contains user 019 * content, reconciliation info, etc.</li> 020 * <li><i>padsUsed</i> - an ordered list of identifiers that indicate what parts 021 * of the sender and recipient's shared one-time pad were used to encrypt this 022 * message</li> 023 * <li><i>mac</i> - a <code>HyperMAC</code> object representing the HEMAC of 024 * this message</li> 025 * <li><i>content</i> - the contents of the message</li> 026 * <li><i>date</i> - the date of the message; the date at which the message was 027 * sent or received</li> 028 * </ul> 029 * 030 * HyperMessages are immutable. 031 */ 032 public class HyperMessage implements Serializable { 033 private static final long serialVersionUID = 1L; 034 035 private final int id; 036 private final HyperMessageType type; 037 private final Contact sender; 038 private final Contact recipient; 039 private final String subject; 040 private final String content; 041 private final HyperMAC hemac; 042 private final List<Integer> padsUsed; 043 private final Date date; 044 045 /** 046 * The ID that will be assigned to the next new HyperMessage. (Should not be 047 * modified directly!) 048 */ 049 private static int nextID = 0; 050 051 /** 052 * Returns the ID that should be assigned to the next new HyperMessage 053 * created. The first time this method is called, it returns 0; every 054 * subsequent time, the return value increases by 1. 055 * 056 * @return the next ID that should be allocated to a new HyperMessage. 057 */ 058 protected static final synchronized int getNextID() { 059 return nextID++; 060 } 061 062 // This constructor is private so that the class may not be subclassed, thus 063 // enforcing the immutability requirement. 064 private HyperMessage(HyperMessageType type, Contact sender, Contact recipient, 065 String subject, String content, List<Integer> padsUsed, 066 HyperMAC hemac, Date date) { 067 // Check validity of arguments 068 if (type == null) 069 throw new NullPointerException("type may not be null"); 070 if (sender == null) 071 throw new NullPointerException("sender may not be null"); 072 if (recipient == null) 073 throw new NullPointerException("recipient may not be null"); 074 if (subject == null) 075 throw new NullPointerException("subject may not be null"); 076 if (content == null) 077 throw new NullPointerException("content may not be null"); 078 if (date == null) 079 throw new NullPointerException("date may not be null"); 080 081 this.id = getNextID(); 082 this.type = type; 083 this.sender = sender; 084 this.recipient = recipient; 085 this.hemac = hemac; 086 this.subject = subject; 087 this.content = content; 088 if (padsUsed == null) 089 this.padsUsed = null; 090 else 091 this.padsUsed = new ArrayList<Integer>(padsUsed); 092 this.date = new Date(date.getTime()); 093 } 094 095 /** 096 * Creates and returns a new HyperMessage. The only arguments that may be 097 * <code>null</code> are <code>padsUsed</code> and <code>hemac</code>. A 098 * <code>null</code> value for <code>padsUsed</code> indicates that the 099 * message content is not encrypted. A <code>null</code> value for 100 * <code>hemac</code> indicates that no authentication information is 101 * included. 102 * <p> 103 * <code>padsUsed</code> is copied before it is stored in this HyperMessage. 104 * 105 * @param type 106 * The type of this message. 107 * @param sender 108 * The sender of this message. 109 * @param recipient 110 * The recipient of this message. 111 * @param subject 112 * The subject of this message. 113 * @param content 114 * The content of this message. 115 * @param padsUsed 116 * An ordered list of the IDs of the one-time pad blocks that were used 117 * to encrypt this message. 118 * @param date 119 * The date of this message. 120 * @throws NullPointerException 121 * if any argument other than <code>padsUsed</code> is 122 * <code>null</code> 123 * @return a new HyperMessage with the given parameters 124 */ 125 public static HyperMessage getInstance(HyperMessageType type, Contact sender, 126 Contact recipient, String subject, String content, 127 List<Integer> padsUsed, HyperMAC hemac, Date date) { 128 return new HyperMessage(type, sender, recipient, subject, content, 129 padsUsed, hemac, date); 130 } 131 132 /** 133 * Returns the unique ID of this message. 134 * @return The unique ID of this message. 135 */ 136 public int getID() { 137 return id; 138 } 139 140 /** 141 * Returns the type of this message. 142 * @return The type of this message. 143 */ 144 public HyperMessageType getType() { 145 return type; 146 } 147 148 /** 149 * Returns the sender of this message. 150 * @return The sender of this message. 151 */ 152 public Contact getSender() { 153 return sender; 154 } 155 156 /** 157 * Returns the recipient of this message. 158 * @return The recipient of this message. 159 */ 160 public Contact getRecipient() { 161 return recipient; 162 } 163 164 /** 165 * Returns the subject of this message. 166 * @return The subject of this message. 167 */ 168 public String getSubject() { 169 return subject; 170 } 171 172 /** 173 * Returns the content of this message. 174 * @return The content of this message. 175 */ 176 public String getContent() { 177 return content; 178 } 179 180 /** 181 * Returns a list of IDs of blocks used to encrypt this message. The list is a 182 * copy; callers are free to mutate the returned list. 183 * @return The IDs of blocks used to encrypt this message. 184 */ 185 public List<Integer> getPadsUsed() { 186 if (padsUsed == null) 187 return null; 188 return new ArrayList<Integer>(padsUsed); 189 } 190 191 /** 192 * Returns the HEMAC for this message. 193 * @return the HEMAC for this message 194 */ 195 public HyperMAC getMac() { 196 return hemac; 197 } 198 199 /** 200 * Returns the date of this message. 201 * @return The date of this message. 202 */ 203 public Date getDate() { 204 return new Date(date.getTime()); 205 } 206 207 /** 208 * Compares this HyperMessage to the specified object. The result is 209 * <code>true</code> if and only if the argument is not <code>null</code> and 210 * is a HyperMessage object with the same ID as this HyperMessage. 211 */ 212 @Override 213 public boolean equals(Object o) { 214 if (o == null || !(o instanceof HyperMessage)) { 215 return false; 216 } 217 218 HyperMessage hm = (HyperMessage)o; 219 return this.id == hm.getID(); 220 } 221 222 @Override 223 public int hashCode() { 224 return id; 225 } 226 }