diff --git a/output/comp210_labs.html b/output/comp210_labs.html
index 48ba0d1..00b5d86 100644
--- a/output/comp210_labs.html
+++ b/output/comp210_labs.html
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5fc74a865bbba2debeb8d3815b153a921f0a81584941f3f860d925b4bcd40f72
-size 3277159
+oid sha256:57fec507c5f277dc8b7ae0015a5e02ae44e6c66572a8aa28edd777439a79497a
+size 3279782
diff --git a/tiddlers/content/labs/03/_Labs_03_Attacking a leaked password hash list.md b/tiddlers/content/labs/03/_Labs_03_Attacking a leaked password hash list.md
index 30404ce..c7288c7 100644
--- a/tiddlers/content/labs/03/_Labs_03_Attacking a leaked password hash list.md
+++ b/tiddlers/content/labs/03/_Labs_03_Attacking a leaked password hash list.md
@@ -1 +1,9 @@
-TODO
\ No newline at end of file
+We have a couple of files containing information about leaked real-world passwords that you can use in the exercises in this section:
+
+
+* [RockYou top 1000, MD5 hashes only](https://blackboard.otago.ac.nz/bbcswebdav/courses/COMP210_S2DNI_2022/huge-files/rockyou_top_1k_md5sums_only.txt)
+* [haveibeenpwned top 1000, SHA1 hashes](https://blackboard.otago.ac.nz/bbcswebdav/courses/COMP210_S2DNI_2022/huge-files/pwned_top_1k_sha1.txt)
+
+**Exercise**: Pick a hash from near the top of the RockYou Top 1000 and see how easily you can crack it using your Python functions.
+
+**Exercise**: Plot the frequencies of the Pwned Top 1000 and comment on the distribution.
\ No newline at end of file
diff --git a/tiddlers/content/labs/03/_Labs_03_John the Ripper.md b/tiddlers/content/labs/03/_Labs_03_John the Ripper.md
index f43a1c3..539b0e2 100644
--- a/tiddlers/content/labs/03/_Labs_03_John the Ripper.md
+++ b/tiddlers/content/labs/03/_Labs_03_John the Ripper.md
@@ -1,3 +1,5 @@
+**Unfortunately, the version of John the Ripper in the lab environment is very old and lacks support for the `mask` parameter, so this section will be for information only.**
+
In this section, we will briefly introduce [John the Ripper](https://www.openwall.com/john/), an open-source password cracking tool (officially termed a "security auditing and password recovery tool"). The following exercises briefly illustrate its use.
First, we can calculate the hash of a readily-crackable password:
diff --git a/tiddlers/content/labs/03/_Labs_03_Password hashing schemes.md b/tiddlers/content/labs/03/_Labs_03_Password hashing schemes.md
index 75ae6df..ede2047 100644
--- a/tiddlers/content/labs/03/_Labs_03_Password hashing schemes.md
+++ b/tiddlers/content/labs/03/_Labs_03_Password hashing schemes.md
@@ -2,7 +2,7 @@
Whereas MD5 can apply directly to an input value, scrypt requires some additional parameters:
* A salt (which ideally would be random bytes).
-* A cost factor `n`, which influences CPU and memory load. This must be a power of 2.
+* A cost factor `n`, which influences CPU and memory load. This must be a power of 2, and the standard suggested value is 16384.
* A block size `r`, which influences memory access patterns. A common value for this is 8.
* A parallelisation factor `p`.
@@ -22,12 +22,14 @@
**Exercise**: Make a copy of the Python `crack` function named `crack_scrypt`, and modify the code so that it uses the `hashlib.scrypt()` function instead of `hashlib.md5()`. Add an additional parameter `work_factor` which maps to the scrypt `n` value; your function's signature should be `def crack_scrypt(target_hash, work_factor, alphabet, max_length):`. To keep things simple, use the values shown in the example above for the other parameters.
-**Exercise**: Perform timing tests using your `crack_scrypt` function with a `max_length` of 4 (to keep timings reasonable) and an alphabet of lowercase letters only. How do the computation times compare with the MD5 case? How does the time vary as you increase the value of `n`? (Remember that `n` must be a power of 2, e.g. 2, 4, 8, 16, etc.)
+**Exercise**: Perform a series of timing tests using your `crack_scrypt` function, to find out how the speed of scrypt compares with plain MD5, and how it varies with the work factor `n`. To keep the timings reasonable, use the lowercase `letters` alphabet and a `max_length` of 2. Start with the recommended work factor of 16384, and halve this number for each successive test (8192, 4096, etc.), plotting your results in a spreadsheet. You only need to test work factors down to 128.
To help you carry out the timing tests easily, use the following code as a single line (and if you are comfortable with Python programming already, you could automate the timing tests using a loop):
```
-start = timer(); crack_scrypt(target_hash, work_factor=2, alphabet=letters, max_length=4); end = timer(); print(end - start, "seconds")
+start = timer(); crack_scrypt(target_hash, work_factor=1024, alphabet=letters, max_length=4); end = timer(); print(end - start, "seconds")
```
+How do the computation times compare with the MD5 case? How does the time vary as you increase the value of `n`?
+
**Exercise**: Discuss the significance of the `salt` parameter, especially in terms of how it would affect a brute-force attack like the ones in this lab. What would be the implications of using a predictable salt value?
\ No newline at end of file