diff --git a/lms/djangoapps/verify_student/ssencrypt.py b/lms/djangoapps/verify_student/ssencrypt.py
index 862c5aa0218ea3416a540eb18e06a7ba0b6dd7d4..3a110b8d0463e8b903ddab7e66c472c79695483f 100644
--- a/lms/djangoapps/verify_student/ssencrypt.py
+++ b/lms/djangoapps/verify_student/ssencrypt.py
@@ -127,9 +127,7 @@ def generate_signed_message(method, headers_dict, body_dict, access_key, secret_
     """
     Returns a (message, signature) pair.
     """
-    headers_str = "{}\n\n{}".format(method, header_string(headers_dict))
-    body_str = body_string(body_dict)
-    message = headers_str + body_str
+    message = signing_format_message(method, headers_dict, body_dict)
 
     # hmac needs a byte string for it's starting key, can't be unicode.
     hashed = hmac.new(secret_key.encode('utf-8'), message, sha256)
@@ -139,6 +137,18 @@ def generate_signed_message(method, headers_dict, body_dict, access_key, secret_
     message += '\n'
     return message, signature, authorization_header
 
+def signing_format_message(method, headers_dict, body_dict):
+    """
+    Given a dictionary of headers and a dictionary of the JSON for the body,
+    will return a str that represents the normalized version of this messsage
+    that will be used to generate a signature.
+    """
+    headers_str = "{}\n\n{}".format(method, header_string(headers_dict))
+    body_str = body_string(body_dict)
+    message = headers_str + body_str
+
+    return message
+
 def header_string(headers_dict):
     """Given a dictionary of headers, return a canonical string representation."""
     header_list = []
@@ -152,7 +162,7 @@ def header_string(headers_dict):
 
     return "".join(header_list) # Note that trailing \n's are important
 
-def body_string(body_dict):
+def body_string(body_dict, prefix=""):
     """
     This version actually doesn't support nested lists and dicts. The code for
     that was a little gnarly and we don't use that functionality, so there's no
@@ -160,9 +170,18 @@ def body_string(body_dict):
     """
     body_list = []
     for key, value in sorted(body_dict.items()):
-        if value is None:
-            value = "null"
-        body_list.append(u"{}:{}\n".format(key, value).encode('utf-8'))
+        if isinstance(value, (list, tuple)):
+            for i, arr in enumerate(value):
+                if isinstance(arr, dict):
+                    body_list.append(body_string(arr, u"{}.{}.".format(key, i)))
+                else:
+                    body_list.append(u"{}.{}:{}\n".format(key, i, arr).encode('utf-8'))
+        elif isinstance(value, dict):
+            body_list.append(body_string(value, key + ":"))
+        else:
+            if value is None:
+                value = "null"
+            body_list.append(u"{}{}:{}\n".format(prefix, key, value).encode('utf-8'))
 
     return "".join(body_list) # Note that trailing \n's are important