Introduction
Instructors usually post a list of student numbers and corresponding marks on their office door. This year I used a method that makes it possible to post the marks on a public internet site without revealing either the student numbers or marks.
Method
I did this by creating an HTML page containing encrypted text and some javascript. Each student’s mark is encrypted using a different password. These passwords are handed out in class or distributed by e-mail before the end of the term.
The HTML file has a form for the student to enter their student ID and password. When the “Show Marks” button is pushed, the script goes through the embedded array of encrypted text strings trying to decrypt each one in turn. It displays the cleartext of the first string that can be successfully decrypted using the ID and password entered into the HTML form.
The text strings are encrypted with AES-256 using the openssl command:
openssl enc -aes-256-cbc -in filename -pass pass:pw -e -base64
where pw is the passphrase created by concatenating the student ID and password and filename is the file with the text to be encrypted. The encrypted output is retrieved from the program’s output by a script (see below).
Below is the HTML file with most of the AES-256 library code and most of the marks removed to make the listing shorter. It consists of two scripts and an HTML form. The first script contains the AES functions from the crypto-js libraries. The second script contains an array with the encrypted marks and the showmarks() function that runs when the “Show Marks” button is pressed.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Marks Retrieval</title> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <script> /* CryptoJS v3.1.2 code.google.com/p/crypto-js (c) 2009-2013 by Jeff Mott. All rights reserved. code.google.com/p/crypto-js/wiki/License */ var CryptoJS=CryptoJS|... </script> <script> // display AES-256-encrypted marks // each string in marks[] is encrypted using a different key formed by // concatenating the student ID and password // shows the first string successfully decoded or an error message // Ed.Casas 2014.5.20 var marks = [ "U2FsdGVkX1+1n6THnLZjnd+fww+qxOpE++J5oqdByEyYXXsqHv6/Qm99wqZ+Xeph8+aFrA/r+zkvYGYMzemcCF5snTJ41ArJR7x5JFWHu2hIl60YD/zHEwyAMEbEVLIwxBtm8tARBu/C32B/CiOzx0BlM6q2F5w+Cbk78y5+0HUptNsgIc8CTyRFlaNmssJypj39VXYUHyTNL34mG8FvhC3L6yu+hp45F/XZkwMK/VjUmn7iwLqFsYuJtp0x8VkhlJPLBMGHe9Is+1E1D/3BHP4C4n7iOjHjntS9YxFhrcZNd80KzvylOdfNLLQ6+Zg1VhBY3rkA2xi4u4Yd9puhMoVBK4Q887GPNBgdvTntl8nl5Yf/o4OKHMhRqDftbu7aGIqbUSsOyo4/uxF5KUQf/Ja7gT3COK2nUqrMZD6UZM6VOhA6pbXZZqrsYotDI3HjpKdRizrAUt/Sp4NC12tfTBUYQxC1fcYPxNZhbjNlXQEi9oHpJTFDP+93LtqMeu5GPpV8dAWMY06GEE3sbwp6sLcbiVix4hPbNiJNGax0psGXL9hfTeCJqBFL0slUKy+ZkyAXGi9q9pKgdZ0RJnBYHg6OWStCDjBXBJLo/J1gYdyJOiZ+l2cAYA2hcsQ3H4sCeBzDtGM2r0eppA9Gkq6BG3rbzhvmgJROQ/6n2rtimnlM0Or3EELiKUbt6oM+vweyUlVr3BUm7yAvup1HwtbkkztSqoeB2OqnFvSBABOP8EHsxuF9lSJItAkibNDCMWXyxBXVR4KpkW+80j2wpjzJ04/J9swLgogpUsfR9l1BhPW1Uzs5Vr33oD5VhzYZsGfYXp+IqG8L3Rd9D7JeiqHzeSSa/x+T7aN876KARb8HnbtEXVbN/eJutmvvnxIbWiHrxYQa5nGkB6mJ2ItYTIGCvt4TIa0DJjTB5kAdb/cHxosFelV75yU61pBjC04r/uhFHRnQs8Bft/2NKhqNvp6rcf7LCkgtW6Psfv8NHnosm9fZgxq6Uiji7YCUq0By6lmDmhKT8yduvbJT2rbnRhm5irfcbLMgge6XJyuhy4Y15Q2pj0fPpnQm2zTU4VuDvzjsOr5bx09vQvjiVQYiJfnXyc31jx+yzmlLg1etUxGV1+9tTSjDCYdAmduvXF0PLh7Q" ] ; function showmarks() { var form = document.getElementById( "form" ) ; var key = form.elements[ "id" ].value + form.elements[ "pw" ].value ; for ( var i in marks ) { try { var decrypted = CryptoJS.AES.decrypt( marks[i], key ) ; var s = decrypted.toString(CryptoJS.enc.Utf8) ; break ; } catch (e) { continue ; } } document.getElementById( "marks" ).innerHTML = s || "Marks not found. Check ID and password." ; } </script> </head> <body onload="document.getElementById('warning').innerHTML=''"> <h2>Show Marks</h2> <span id="warning" style="color:red">Warning: Your marks are displayed by a script but Javascript may not be enabled.</span> <form id="form"> BCIT ID (starting with A): <input type="text" id="id"><br> mark retrieval password: <input type="password" id="pw"><br> <input type="button" value="Show Marks" onclick="showmarks()"> </form> <hr> <pre id="marks"></pre> </body>
Where does the text come from? In this case it comes from a spreadsheet used to calculate the marks. The spreadsheet is exported in CSV format and an AWK script is used to add some formatting and encrypt each line using an ID and password found in specific columns of the spreadsheet. This is done using the system and getline awk functions.
The AWK script also automates the process so that only one command needs to be entered to create the new HTML file each time the spreadsheet is updated.
Example
Below is a screen capture of the interface and output when accessed via the D2L LMS for one of my courses. Each row of the output corresponds to the contents of one spreadsheet column for this (fictional) student:
Alternatives
Why didn’t I just use the D2L grading system which makes the marks available to the students in secure fashion? I found the D2L system was not flexible enough and much more cumbersome to use than a spreadsheet.
Why not distribute the marks using D2L or by e-mail? As far as I know, D2L provides no (simple) mechanism to distribute confidential material to students in an automated fashion.
Other Applications
The advantages of this technique are:
- almost any browser can be used to decrypt and retrieve the information, and
- the information can be distributed using a public web site or a mailing list without compromising the privacy of the data.
Therefore this technique may also be useful when it’s necessary to distribute confidential information to people who may not have specific decryption software (e.g. due to legal restrictions).
Leave a Reply