package stevens.cs396.mac; import java.security.Key; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.SecretKeySpec; // DO NOT MODIFY public abstract class MacSkeleton { public static final String KEY_ALGO =
package stevens.cs396.mac;
import java.security.Key; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.SecretKeySpec;
// DO NOT MODIFY public abstract class MacSkeleton {
public static final String KEY_ALGO = "AES"; public static final String MODE = KEY_ALGO + "/ECB/NoPadding"; public static final int BLOCK_SIZE = 128 / 8; public static final int KEY_SIZE = 128 / 8;
public static int getBlockSize() { return BLOCK_SIZE; }
/** * Generates a key given some secret. Pads or truncates it to the correct * key size. * @param secret Secret to generate key from * @return A Key generated from the secret */ public static Key generate(byte[] secret) { byte[] key = new byte[KEY_SIZE]; System.arraycopy(secret, 0, key, 0, Math.min(secret.length, KEY_SIZE)); return new SecretKeySpec(key, KEY_ALGO); }
/** * Performs a bitwise XOR on two byte arrays and returns the result as * a new byte array. * @param a First byte array * @param b Second byte array * @return The result of a bitwise XOR of both arrays. */ public static byte[] xor(byte[] a, byte[] b) { byte[] rv = new byte[Math.max(a.length, b.length)]; System.arraycopy((a.length > b.length ? a : b), 0, rv, 0, rv.length); for (int i = 0, l = Math.min(a.length, b.length); i < l; ++i) { rv[i] = (byte) (a[i] ^ b[i]); } return rv; }
/** * Takes a message and a block size in bytes and pads the message to that * block size with 100... Adds an additional block if needed. * @param message message to pad * @param blockSz block size to pad the message to * @return message padded out to the right block size */ public static byte[] pad(byte[] message, int blockSz) { byte[] rv = new byte[((message.length/blockSz) + 1) * blockSz]; System.arraycopy(message, 0, rv, 0, message.length); rv[(message.length)] = (byte) 0x80; return rv; }
/** * Encrypts a single block. Input block must be of the correct block * size. * @param block A single block of plaintext, of size BLOCK_SIZE * @param key The key to use for encrypting the plaintext * @return The ciphertext generated from encrypting the plaintext */ public static byte[] encryptBlock(byte[] block, Key key) throws Exception { if (block == null || block.length != BLOCK_SIZE) { throw new IllegalArgumentException( "Block must be size " + BLOCK_SIZE); }
Cipher c = Cipher.getInstance(MODE); c.init(Cipher.ENCRYPT_MODE, key); return c.doFinal(block); }
public abstract byte[] mac(byte[] message, Key key); public abstract boolean verify(byte[] message, byte[] tag, Key key);
}
=================================================================
=================================================================
package stevens.cs396.mac;
import java.security.Key;
// Implement this class public class Mac extends MacSkeleton {
/** * Implement the mac and verify methods. Mac should take a message and a * key (generated by the generate method) and return a tag. Verify should * take a message, tag, and key -- and authenticate that the tag corresponds * to the message/tag pair by returning true or false. * * The following methods have been made available to you through the * MacSkeleton class: * * byte[] xor(byte[] a, byte[] b) :: XOR two byte arrays. Returns result * byte[] pad(byte[] message, int blockSz) :: pads message to blockSz * byte[] encryptBlock(byte[] block, Key key) :: Encrypts a single block * int getBlockSize() :: Returns the block size of the cipher */
/** * Creates a message authentication tag for a message with a given key. * @param message The message to generate a MAC for * @param key A secret key to use for MAC'ing the message * @return A valid tag for the message */ public byte[] mac(byte[] message, Key key) { // TODO return null; }
/** * Authenticates a message/tag pair with a key. Returns true if the pair * is authentic, else false. * @param message message to authenticate * @param tag a MAC tag to authenticate with the message * @param key secret key to authenticate the tag with */ public boolean verify(byte[] message, byte[] tag, Key key) { // TODO return false; }
}
=================================================================
=================================================================
import java.security.Key; import javax.xml.bind.DatatypeConverter;
public class Main {
public static void main(String[] args) { boolean verify = false; String message = "This is a test message. There are many like it but" + " this one is mine."; String secret = "CS-396_Test_Key"; byte[] tag = null;
switch (args.length) { case 3: verify = true; tag = toByteArray(args[2]); case 2: secret = args[1]; case 1: message = args[0]; break; case 0: break; default: System.err.println("Unexpected number of params"); usage(); System.exit(1); break; }
Mac mac = new Mac(); Key key = mac.generate(secret.getBytes());
System.err.println("## Key ## " + secret + " "); System.err.println("## Message ## " + message + " "); if (!verify) { tag = mac.mac(message.getBytes(), key); } System.err.println("## Tag ## " + toHexString(tag) + " ");
if (mac.verify(message.getBytes(), tag, key)) { System.err.println("Success, tag was verified."); } else { System.err.println("Error, tag was not verified."); } }
public static String toHexString(byte[] array) { return DatatypeConverter.printHexBinary(array); }
public static byte[] toByteArray(String s) { return DatatypeConverter.parseHexBinary(s); }
public static void usage() { System.err.println("usage: java stevens.cs396.mac.Main [message [key [tag]]]"); }
}
====================================================================
Domain-extension MAC implementation
Given the provided support code in Java, implement a secure secret-key message authentication code that employs only a block cipher (and no other cryptographic primitive) to authenticate messages of any size in a bandwidth-efficient manner. In particular, as specified in the provided instructions:
1) Implement the mac() and verify() methods.
2) Demonstrate that they are correct by providing the MAC tag (in hexidecimal) of the specified default message using the specified default key.
3) Explain which of the MAC algorithms covered in class you implemented and why. What are the domain-extension features of your algorithm in relation to its security?
***Hint: Does your implementation securely handle messages of fixed size, messages of any size, or messages of any fixed size?
*** Please complete the code NOT an essay response! Thank you
Step by Step Solution
There are 3 Steps involved in it
Step: 1
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started