Programming Assignment 2 Winter 2024
CS 255: Intro to Cryptography
Prof. Dan Boneh Due Tuesday, March 5, 11:59pm
1 Introduction
In this assignment, you are tasked with implemenng a secure and ecient end-to-end encrypted chat
client using the Double Ratchet Algorithm, a popular session setup protocol that powers realworld chat
systems such as Signal and WhatsApp. As an addional challenge, assume you live in a country with
government surveillance. Thereby, all messages sent are required to include the session key encrypted
with a xed public key issued by the government. In your implementaon, you will make use of various
cryptographic primives we have discussed in class—notably, key exchange, public key encrypon, digital
signatures, and authencated encrypon. Because it is ill-advised to implement your own primives in
cryptography, you should use an established library: in this case, the SubtleCrypto library. We will provide
starter code that contains a basic template, which you will be able to ll in to sasfy the funconality and
security properes described below.
2 End-to-end Encrypted Chat Client
2.1 Implementation Details
Your chat client will use the Double Ratchet Algorithm to provide end-to-end encrypted communicaons
with other clients. To evaluate your messaging client, we will check that two or more instances of your
implementaon it can communicate with each other properly.
We feel that it is best to understand the Double Ratchet Algorithm straight from the source, so we ask that
you read Secons 1, 2, and 3 of Signal’s published specicaon here: hps://signal.
org/docs/specicaons/doubleratchet/. Your implementaon must correctly use the Double Ratchet
Algorithm as described in Secon 3 of the specicaon, with the following changes and claricaons:
You may use HKDF to ratchet the Die-Hellman keys the as described in Secon 2.3 ohe Signal
Specicaon. Proper usage of HKDF is explained in Secon 5.2 of the Signal
Specicaon.
HKDF is a key derivaon funcon that we’ve added to lib.js. Secon 5.2 describes how itcan be used
in your implementaon. Read the lib.js comments for how to use our API.
The lib.js funcons contains two HMAC-related funcons: HMACtoAESKey (used to generate keys
for AES encrypon/decrypon) and HMACtoHMACKey (used to generate keys for further HMACs).
Part of your task is determining which funcon to use in each case in order to implement the Signal
algorithm.
Use ElGamal key pairs for the Die-Hellman key exchange. See the generateEG funcon in lib.js.
Use AES-GCM as the symmetric encrypon algorithm for encrypng messages, using thesending and
receiving keys as derived in Secon 2.4.
Disregard the AD byte sequence input for the ratchetEncrypt and ratchetDecrypt funcons in the
Signal Specicaon. Message headers should sll be be authencated.
The header of all sent messages must include an encrypon of the sending key under the gov-
ernment’s public key. Use ElGamal public key encrypon, with AES-GCM as the symmetric cipher, to
encrypt the sending keys. (Note: Since the output of the computeDH funcon is congured with
HMAC, you will need to run the output through HMACtoAESKey to generate a key that can be used
with AES-GCM. Please use the govEncryponDataStr variable as the data parameter in your call to
HMACtoAESKey. It may be helpful to refer to the govDecrypt funcon in test-messenger.js to see
how the govEncryponDataStr variable is used during decrypon.)
Every client will a possess an inial ElGamal key pair. These key changes will be used toderive inial
root keys for new communicaon sessions.
Public keys will be distributed through simple cercates. Each client generates its owncercate
upon inializaon which contains its ElGamal public key. Assume that there is some trusted central
party (e.g. server managed by developers of messaging app), and that this central party can securely
receive cercates generated by clients. This central party generates a digital signature on each
cercate that it obtains, which serves to endorse the authencity of the cercate owners identy
and to prevent any tampering of the cercate by an adversary. The signed cercates are then
distributed back to the clients, so that every client has the ElGamal public key of every other client
in the system.
Please note that you should generate a new random IV every me you encrypt with AES-GCM. You
can use the genRandomSalt funcon from lib.js to generate this IV. Keep in mind that your
implement can store IVs in plaintext in message headers and in fact you will need to store IVs in the
message headers.
You do not need to handle and recover from dropped or out-of-order messages. You do notneed to
worry about Secon 2.6 of the specicaon. You can assume that a message being sent and received
together constute an atomic operaon, meaning if a message is sent, the very next acon that
occurs is that the same message will be received by the other party. It will never be the case that
two messages are sent before the rst one is received. If you detect that a message has been
blocked, dropped, or received out of order, throw an excepon.
The memory cost of key storage for your algorithm should always be O(1) and independentof the
number of messages sent. In order to sasfy this, your implementaon will discard old keys
whenever a ratchet occurs.
2.2 Threat model
The goal of the Double-Ratchet algorithm is to provide Forward Secrecy: compromise of long term keys or
current session key must not compromise past communicaons.
Specically, consider a Man-in-the-Middle aacker Eve who sits between Alice and Bob. Eve sees every
encrypted message passed between Alice and Bob and writes all of them to persistent storage. Then at
some point, Alice’s device is compromised and Eve learns Alice’s current secret keys. (Assume that Alice
has deleted her keys for old messages, as encouraged by the Signal Specicaon.) Your implementaon
must ensure that under this scenario, the aacker cannot decrypt any of the past messages in her
persistent storage despite having full access to Alice’s current keys.
Aer Alice’s keys are compromised, the adversary can now launch an acve Man-in-the-Middle aack. She
impersonates both pares and is able to decrypt all communicaons between Alice and Bob. However, at
some later point, Alice manages to send a single message to Bob without the aacker being able to
intercept it. Under this scenario, your implementaon must ensure that the aacker loses all ability to
decrypt communicaons once again. This property is called Break-in Recovery.
Implemenng the Double-Ratchet algorithm as dened in the Signal documentaon is sucient to ensure
these two properes.
Adding the sending key encrypted under the governments public key should not compromise the security
properes of the chat client. The government should be able to use its secret key to decrypt any message;
however no one else, other than the intended recipient, should be able to learn anything about the
message contents.
3 API description
Here are descripons of the funcons you will need to implement.
3.1 messenger.generateCercate(username)
This method should inialize the messenger client for communicaons with other clients. Generate the
necessary ElGamal key pair for key exchanges. Public keys are are placed into a cercate to send to other
clients. You are free to design your own cercate object, so long as it has a eld called “username”.
3.2 messenger.receiveCercate(cercate, signature)
This method takes a cercate from another client and stores it in the messengers internal state, so that
the client can now send and receive messages from the owner of that cercate. The second argument is
the trusted central partys signature of the cercate. You must verify the validity of the signature (using
the trusted central party’s public key, provided to you in the messenger class constructor) to ensure that
the cercate has not been modied by an adversary. If you detect tampering, immediately throw an
excepon to end program execuon.
3.3 messenger.sendMessage(name, message)
Send an encrypted message to the user specied by name. You can assume you already possess their
cercate through messenger.receiveCercate, and that they already possess your cercate. If you have
not previously communicated, setup the session by generang the necessary double ratchet keys
according to the Signal spec. On every send, increment the sending chain (and the root chain if necessary,
according to the Signal spec). Create a header including the data necessary for other party to derive the
new key, in addion to the new sending key encrypted with the governments public key. The header must
include the elds “vGov” and cGov” which denote the outputs (v,c) of the ElGamal public key encrypon.
You will also need to pass an “ivGov containing the IV used to encrypt the message key for the
government and a “receiverIV” containing the IV used to encrypt the message for the receiver. Each
header will contain two randomly generated IVs in total. Lastly, with the new sending key, encrypt the
message with the header passed as authencated data. Every message must be encrypted with a new
sending key.
3.4 messenger.receiveMessage(name, [header, ciphertext])
Receive an encrypted message from the user specied by name. You can assume you already possess their
cercate through messenger.receiveCercate, and that they computed the inial root key using the
ElGamal key from your cercate. If you have not previously communicated, setup the session by
generang necessary double ratchet keys according to the Signal spec. On every receive, increment the
receiving chain (and the root chain if necessary, according to the Signal spec) using the informaon
provided in the header, and decrypt with a new receiving key. If tampering is detected in any way, throw
and excepon to terminate the program (i.e. the adversary has tampered with your ciphertext).
4 Setup Instructions
The setup process is essenally the same as with Project 1, as this project is also based in Node.
Extract the starter code and cd into the directory proj2. You will need to run npm install – this will install
the dependencies specied in the package.json le locally, into a new directory named node_modules
under proj2. You should now be all set. We have provided a test suite, which you can run using the
command npm test from this directory. These are the same tests that the autograder will be running.
There are no hidden test cases. The autograder will be running Node version 18.
4.1 Linting
The provided package.json includes a linng script, which can help you nd simple bugs and style issues.
To run the linter, run npm run lint. The linter can also x some formang errors in your code. To have the
linter automacally apply the xes it can, run npm run lint-x. The linter is provided for your convenience.
The autograder will NOT be running the linter.
5 Hints and Summary
All the code you will have to write will be in the le messenger.js. Please do not write any code in
another le.
Your messaging system will depend on the SubtleCrypto library for its underlying
cryptoimplementaon. However, you should not need to call the SubtleCrypto funcons directly
(and our starter code does not include it directly). We have provided a support code library, lib.js,
which provides wrappers for any SubtleCrypto funcons that you should need.
Be sure to review the comments in the lib.js le to understand what the data types and inputs and
outputs of various funcons are.
Since SubtleCrypto is an inherently asynchronous library, almost all of the funcons in lib.js are
asynchronous. If you are running into errors about values being undened, check to make sure that
each call to an asychronous funcon is preceeded by an await or followed by a .then(). If you refer
to test/test-messenger.js you will see many examples of the await keyword being used.
You can have a look at the tests being run in the le test/test-messenger.js. You are always welcome
to write more tests to make sure your implementaon sases the requirements, but you are not
required to, and we will not be grading your tests. The tests are wrien using the MochaJS
framework (hps://mochajs.org/) with Chai for asserons (hp://chaijs.com/), and should be fairly
readable.
If your applicaon detects tampering with any of its in-transit data (e.g. ciphertexts, signa-tures,
etc.), it should throw an excepon (thereby terminang the execuon). We will not test what
excepon is thrown; it is ne to throw a string with an English descripon of the potenal tampering.
6 Extra Credit
We will award 10% extra credit for successfully handling messages that are dropped, delayed or delivered
out-of-order. How this can be achieved is described in secon 2.6 of the Signal DoubleRatchet
specicaon, and the full algorithm as described in secon 3 of the spec includes handling such messages.
Suppose two messages A and B are delivered out-of-order i.e. B arrives before A. A successful
implementaon will be able decrypt B as soon as it arrives without having to wait for A, yet will sll be
able decrypt A when it does nally arrive. For full extra-credit, you should be able to decrypt A even if an
arbitrary number of messages arrive in between B and A.
We strongly recommend you rst implement the project without aempng the extra credit poron.
7 Short-answer Questions
In addion to your implementaon, please include answers to the following quesons regarding your
implementaon. Your answers need not be long, but should include important details.
Please submit typed or handwrien answers to the “Project #2 Short-answer Quesons” assignment
on Gradescope (separate from programming component).
1. In our implementaon, Alice and Bob increment their Die-Hellman ratchets every me
theyexchange messages. Could the protocol be modied to have them increment the DH ratchets
once every ten messages without compromising condenality against an eavesdropper (i.e.,
semanc security)?
2. What if they never update their DH keys at all? Please explain the security consequences ohis
change with regards to Forward Secrecy and Break-in Recovery.
3. Consider the following conversaon between Alice and Bob, protected via the Double
RatchetAlgorithm according to the spec:
A: Hey Bob, can you send me the locker combo?
A: I need to get my laptop B: Sure , it s
1234!
A: Great , thanks ! I used it and deleted the previous message . B: Did it work?
What is the length of the longest sending chain used by Alice? By Bob? Please explain.
4. Unfortunately, in the situaon above, Mallory has been monitoring their communicaonsand nally
managed to compromise Alice’s phone and steal all her keys just before she sent her third message.
Mallory will be unable to determine the locker combinaon. State and describe the relevant security
property and jusfy why double ratchet provides this property.
5. The method of government surveillance is deeply awed. Why might it not be as eecve
asintended? What are the major risks involved with this method?
6. The SubtleCrypto library is able to generate signatures in various ways, including both ECDSA and
RSA keys. For both the ECDSA and RSA-based signature techniques, please compare:
(a) Which keys take longer to generate (ming SubtleCrypto.generateKey)
(b) Which signature takes longer to generate (ming SubtleCrypto.sign)
(c) Which signature is longer in length (length of output of SubtleCrypto.sign)
(d) Which signature takes longer to verify (ming SubtleCrypto.verify)
Note: For this queson, you can choose to conjecture what the right answer might be or run the
script provided in the starter code (in folder /queson6code). A well jused conjecture that may
not be fully correct can sll receive full credit. To run the code in /queson6code, navigate to the
folder in your terminal and then execute the command node q6code.js.

Preview text:

Programming Assignment 2 Winter 2024 CS 255: Intro to Cryptography Prof. Dan Boneh
Due Tuesday, March 5, 11:59pm 1 Introduction
In this assignment, you are tasked with implementing a secure and efficient end-to-end encrypted chat
client using the Double Ratchet Algorithm, a popular session setup protocol that powers realworld chat
systems such as Signal and WhatsApp. As an additional challenge, assume you live in a country with
government surveillance. Thereby, all messages sent are required to include the session key encrypted
with a fixed public key issued by the government. In your implementation, you will make use of various
cryptographic primitives we have discussed in class—notably, key exchange, public key encryption, digital
signatures, and authenticated encryption. Because it is ill-advised to implement your own primitives in
cryptography, you should use an established library: in this case, the SubtleCrypto library. We will provide
starter code that contains a basic template, which you will be able to fill in to satisfy the functionality and
security properties described below. 2
End-to-end Encrypted Chat Client 2.1 Implementation Details
Your chat client will use the Double Ratchet Algorithm to provide end-to-end encrypted communications
with other clients. To evaluate your messaging client, we will check that two or more instances of your
implementation it can communicate with each other properly.
We feel that it is best to understand the Double Ratchet Algorithm straight from the source, so we ask that
you read Sections 1, 2, and 3 of Signal’s published specification here: https://signal.
org/docs/specifications/doubleratchet/. Your implementation must correctly use the Double Ratchet
Algorithm as described in Section 3 of the specification, with the following changes and clarifications:

• You may use HKDF to ratchet the Diffie-Hellman keys the as described in Section 2.3 ofthe Signal
Specification. Proper usage of HKDF is explained in Section 5.2 of the Signal Specification.
• HKDF is a key derivation function that we’ve added to lib.js. Section 5.2 describes how itcan be used
in your implementation. Read the lib.js comments for how to use our API.
• The lib.js functions contains two HMAC-related functions: HMACtoAESKey (used to generate keys
for AES encryption/decryption) and HMACtoHMACKey (used to generate keys for further HMACs).
Part of your task is determining which function to use in each case in order to implement the Signal algorithm.
• Use ElGamal key pairs for the Diffie-Hellman key exchange. See the generateEG function in lib.js.
• Use AES-GCM as the symmetric encryption algorithm for encrypting messages, using thesending and
receiving keys as derived in Section 2.4.
• Disregard the AD byte sequence input for the ratchetEncrypt and ratchetDecrypt functions in the
Signal Specification. Message headers should still be be authenticated.
• The header of all sent messages must include an encryption of the sending key under the gov-
ernment’s public key. Use ElGamal public key encryption, with AES-GCM as the symmetric cipher, to
encrypt the sending keys. (Note: Since the output of the computeDH function is configured with
HMAC, you will need to run the output through HMACtoAESKey to generate a key that can be used
with AES-GCM. Please use the govEncryptionDataStr variable as the data parameter in your call to
HMACtoAESKey. It may be helpful to refer to the govDecrypt function in test-messenger.js to see
how the govEncryptionDataStr variable is used during decryption.)
• Every client will a possess an initial ElGamal key pair. These key changes will be used toderive initial
root keys for new communication sessions.
• Public keys will be distributed through simple certificates. Each client generates its owncertificate
upon initialization which contains its ElGamal public key. Assume that there is some trusted central
party (e.g. server managed by developers of messaging app), and that this central party can securely
receive certificates generated by clients. This central party generates a digital signature on each
certificate that it obtains, which serves to endorse the authenticity of the certificate owner’s identity
and to prevent any tampering of the certificate by an adversary. The signed certificates are then
distributed back to the clients, so that every client has the ElGamal public key of every other client in the system.
• Please note that you should generate a new random IV every time you encrypt with AES-GCM. You
can use the genRandomSalt function from lib.js to generate this IV. Keep in mind that your
implement can store IVs in plaintext in message headers and in fact you will need to store IVs in the message headers.
• You do not need to handle and recover from dropped or out-of-order messages. You do notneed to
worry about Section 2.6 of the specification. You can assume that a message being sent and received
together constitute an atomic operation, meaning if a message is sent, the very next action that
occurs is that the same message will be received by the other party. It will never be the case that
two messages are sent before the first one is received. If you detect that a message has been
blocked, dropped, or received out of order, throw an exception.
• The memory cost of key storage for your algorithm should always be O(1) and independentof the
number of messages sent. In order to satisfy this, your implementation will discard old keys whenever a ratchet occurs. 2.2 Threat model
The goal of the Double-Ratchet algorithm is to provide Forward Secrecy: compromise of long term keys or
current session key must not compromise past communications.
Specifically, consider a Man-in-the-Middle attacker Eve who sits between Alice and Bob. Eve sees every
encrypted message passed between Alice and Bob and writes all of them to persistent storage. Then at
some point, Alice’s device is compromised and Eve learns Alice’s current secret keys. (Assume that Alice
has deleted her keys for old messages, as encouraged by the Signal Specification.) Your implementation
must ensure that under this scenario, the attacker cannot decrypt any of the past messages in her
persistent storage despite having full access to Alice’s current keys.
After Alice’s keys are compromised, the adversary can now launch an active Man-in-the-Middle attack. She
impersonates both parties and is able to decrypt all communications between Alice and Bob. However, at
some later point, Alice manages to send a single message to Bob without the attacker being able to
intercept it. Under this scenario, your implementation must ensure that the attacker loses all ability to
decrypt communications once again. This property is called Break-in Recovery.
Implementing the Double-Ratchet algorithm as defined in the Signal documentation is sufficient to ensure these two properties.
Adding the sending key encrypted under the government’s public key should not compromise the security
properties of the chat client. The government should be able to use its secret key to decrypt any message;
however no one else, other than the intended recipient, should be able to learn anything about the message contents. 3 API description
Here are descriptions of the functions you will need to implement.
3.1 messenger.generateCertificate(username)
This method should initialize the messenger client for communications with other clients. Generate the
necessary ElGamal key pair for key exchanges. Public keys are are placed into a certificate to send to other
clients. You are free to design your own certificate object, so long as it has a field called “username”.
3.2 messenger.receiveCertificate(certificate, signature)
This method takes a certificate from another client and stores it in the messengers internal state, so that
the client can now send and receive messages from the owner of that certificate. The second argument is
the trusted central party’s signature of the certificate. You must verify the validity of the signature (using
the trusted central party’s public key, provided to you in the messenger class constructor) to ensure that
the certificate has not been modified by an adversary. If you detect tampering, immediately throw an
exception to end program execution.
3.3 messenger.sendMessage(name, message)
Send an encrypted message to the user specified by name. You can assume you already possess their
certificate through messenger.receiveCertificate, and that they already possess your certificate. If you have
not previously communicated, setup the session by generating the necessary double ratchet keys
according to the Signal spec. On every send, increment the sending chain (and the root chain if necessary,
according to the Signal spec). Create a header including the data necessary for other party to derive the
new key, in addition to the new sending key encrypted with the government’s public key. The header must
include the fields “vGov” and “cGov” which denote the outputs (v,c) of the ElGamal public key encryption.
You will also need to pass an “ivGov” containing the IV used to encrypt the message key for the
government and a “receiverIV” containing the IV used to encrypt the message for the receiver. Each
header will contain two randomly generated IVs in total. Lastly, with the new sending key, encrypt the
message with the header passed as authenticated data. Every message must be encrypted with a new sending key.
3.4 messenger.receiveMessage(name, [header, ciphertext])
Receive an encrypted message from the user specified by name. You can assume you already possess their
certificate through messenger.receiveCertificate, and that they computed the initial root key using the
ElGamal key from your certificate. If you have not previously communicated, setup the session by
generating necessary double ratchet keys according to the Signal spec. On every receive, increment the
receiving chain (and the root chain if necessary, according to the Signal spec) using the information
provided in the header, and decrypt with a new receiving key. If tampering is detected in any way, throw
and exception to terminate the program (i.e. the adversary has tampered with your ciphertext). 4 Setup Instructions
The setup process is essentially the same as with Project 1, as this project is also based in Node.
Extract the starter code and cd into the directory proj2. You will need to run npm install – this will install
the dependencies specified in the package.json file locally, into a new directory named node_modules
under proj2. You should now be all set. We have provided a test suite, which you can run using the
command npm test from this directory. These are the same tests that the autograder will be running.
There are no hidden test cases. The autograder will be running Node version 18. 4.1 Linting
The provided package.json includes a linting script, which can help you find simple bugs and style issues.
To run the linter, run npm run lint. The linter can also fix some formatting errors in your code. To have the
linter automatically apply the fixes it can, run npm run lint-fix. The linter is provided for your convenience.
The autograder will NOT be running the linter. 5 Hints and Summary
• All the code you will have to write will be in the file messenger.js. Please do not write any code in another file.
• Your messaging system will depend on the SubtleCrypto library for its underlying
cryptoimplementation. However, you should not need to call the SubtleCrypto functions directly
(and our starter code does not include it directly). We have provided a support code library, lib.js,
which provides wrappers for any SubtleCrypto functions that you should need.
• Be sure to review the comments in the lib.js file to understand what the data types and inputs and
outputs of various functions are.
• Since SubtleCrypto is an inherently asynchronous library, almost all of the functions in lib.js are
asynchronous. If you are running into errors about values being undefined, check to make sure that
each call to an asychronous function is preceeded by an await or followed by a .then(). If you refer
to test/test-messenger.js you will see many examples of the await keyword being used.
• You can have a look at the tests being run in the file test/test-messenger.js. You are always welcome
to write more tests to make sure your implementation satisfies the requirements, but you are not
required to, and we will not be grading your tests. The tests are written using the MochaJS
framework (https://mochajs.org/) with Chai for assertions (http://chaijs.com/), and should be fairly readable.
• If your application detects tampering with any of its in-transit data (e.g. ciphertexts, signa-tures,
etc.), it should throw an exception (thereby terminating the execution). We will not test what
exception is thrown; it is fine to throw a string with an English description of the potential tampering. 6 Extra Credit
We will award 10% extra credit for successfully handling messages that are dropped, delayed or delivered
out-of-order. How this can be achieved is described in section 2.6 of the Signal DoubleRatchet
specification, and the full algorithm as described in section 3 of the spec includes handling such messages.
Suppose two messages A and B are delivered out-of-order i.e. B arrives before A. A successful
implementation will be able decrypt B as soon as it arrives without having to wait for A, yet will still be
able decrypt A when it does finally arrive. For full extra-credit, you should be able to decrypt A even if an
arbitrary number of messages arrive in between B and A.
We strongly recommend you first implement the project without attempting the extra credit portion. 7 Short-answer Questions
In addition to your implementation, please include answers to the following questions regarding your
implementation. Your answers need not be long, but should include important details.
Please submit typed or handwritten answers to the “Project #2 Short-answer Questions” assignment
on Gradescope (separate from programming component).

1. In our implementation, Alice and Bob increment their Diffie-Hellman ratchets every time
theyexchange messages. Could the protocol be modified to have them increment the DH ratchets
once every ten messages without compromising confidentiality against an eavesdropper (i.e., semantic security)?
2. What if they never update their DH keys at all? Please explain the security consequences ofthis
change with regards to Forward Secrecy and Break-in Recovery.
3. Consider the following conversation between Alice and Bob, protected via the Double
RatchetAlgorithm according to the spec: A: Hey Bob, can you send me the locker combo?
A: I need to get my laptop B: Sure , it ’ s 1234!
A: Great , thanks ! I used it and deleted the previous message . B: Did it work?
What is the length of the longest sending chain used by Alice? By Bob? Please explain.
4. Unfortunately, in the situation above, Mallory has been monitoring their communicationsand finally
managed to compromise Alice’s phone and steal all her keys just before she sent her third message.
Mallory will be unable to determine the locker combination. State and describe the relevant security
property and justify why double ratchet provides this property.
5. The method of government surveillance is deeply flawed. Why might it not be as effective
asintended? What are the major risks involved with this method?
6. The SubtleCrypto library is able to generate signatures in various ways, including both ECDSA and
RSA keys. For both the ECDSA and RSA-based signature techniques, please compare:
(a) Which keys take longer to generate (timing SubtleCrypto.generateKey)
(b) Which signature takes longer to generate (timing SubtleCrypto.sign)
(c) Which signature is longer in length (length of output of SubtleCrypto.sign)
(d) Which signature takes longer to verify (timing SubtleCrypto.verify)
Note: For this question, you can choose to conjecture what the right answer might be or run the
script provided in the starter code (in folder /question6code). A well justified conjecture that may
not be fully correct can still receive full credit. To run the code in /question6code, navigate to the
folder in your terminal and then execute the command node q6code.js.