2 import java.util.HashMap;
3 import java.util.Arrays;
4 import javax.crypto.spec.*;
9 HashMap<IoTString, IoTString> table=new HashMap<IoTString, IoTString>();
10 HashMap<Long, Long> lastmessage=new HashMap<Long, Long>();
17 public Table(String baseurl, String password, long _machineid) {
19 buffer = new SlotBuffer();
21 initCloud(baseurl, password);
24 private void initCloud(String baseurl, String password) {
26 SecretKeySpec secret=getKey(password);
27 Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
28 encryptCipher.init(Cipher.ENCRYPT_MODE, secret);
29 Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
30 decryptCipher.init(Cipher.DECRYPT_MODE, secret);
31 hmac = Mac.getInstance("HmacSHA256");
33 cloud=new CloudComm(baseurl, encryptCipher, decryptCipher, hmac);
34 } catch (Exception e) {
35 throw new Error("Failed To Initialize Ciphers");
39 private SecretKeySpec getKey(String password) {
41 PBEKeySpec keyspec = new PBEKeySpec(password.toCharArray());
42 SecretKey key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(keyspec);
43 SecretKeySpec secret = new SecretKeySpec(key.getEncoded(), "AES");
45 } catch (Exception e) {
46 throw new Error("Failed generating key.");
50 public void update() {
51 Slot[] newslots=cloud.getSlots(sequencenumber);
52 validateandupdate(newslots);
55 void validateandupdate(Slot[] newslots) {
56 //The cloud communication layer has checked slot HMACs already
58 if (newslots.length==0)
61 long firstseqnum=newslots[0].getSequenceNumber();
62 if (firstseqnum < sequencenumber)
63 throw new Error("Server Error: Sent older slots!");
65 SlotIndexer indexer = new SlotIndexer(newslots, buffer);
66 checkHMACChain(indexer, newslots);
67 for(Slot slot: newslots) {
68 processSlot(indexer, slot);
73 void processEntry(KeyValue entry, SlotIndexer indexer, Slot slot) {
77 void processEntry(LastMessage entry, SlotIndexer indexer, Slot slot) {
81 void processEntry(RejectedMessage entry, SlotIndexer indexer, Slot slot) {
85 void processEntry(TableStatus entry, SlotIndexer indexer, Slot slot) {
89 void processSlot(SlotIndexer indexer, Slot slot) {
90 for(Entry entry : slot.getEntries()) {
91 switch(entry.getType()) {
92 case Entry.TypeKeyValue:
93 processEntry((KeyValue)entry, indexer, slot);
95 case Entry.TypeLastMessage:
96 processEntry((LastMessage)entry, indexer, slot);
98 case Entry.TypeRejectedMessage:
99 processEntry((RejectedMessage)entry, indexer, slot);
101 case Entry.TypeTableStatus:
102 processEntry((TableStatus)entry, indexer, slot);
105 throw new Error("Unrecognized type: "+entry.getType());
110 void checkHMACChain(SlotIndexer indexer, Slot[] newslots) {
111 for(int i=0; i < newslots.length; i++) {
112 Slot currslot=newslots[i];
113 Slot prevslot=indexer.getSlot(currslot.getSequenceNumber()-1);
114 if (prevslot != null &&
115 !Arrays.equals(prevslot.getHMAC(), currslot.getPrevHMAC()))
116 throw new Error("Server Error: Invalid HMAC Chain");