def upload_photo_id_image(self, img_data): """ Upload an the user's photo ID image to S3. `img_data` should be a raw bytestream of a PNG image. This method will take the data, encrypt it using a randomly generated AES key, encode it with base64 and save it to S3. The random key is also encrypted using Software Secure's public RSA key and stored in our `photo_id_key` field. Yes, encoding it to base64 adds compute and disk usage without much real benefit, but that's what the other end of this API is expecting to get. """ # Skip this whole thing if we're running acceptance tests or if we're # developing and aren't interested in working on student identity # verification functionality. If you do want to work on it, you have to # explicitly enable these in your private settings. if settings.FEATURES.get( 'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING'): return aes_key = random_aes_key() rsa_key_str = settings.VERIFY_STUDENT["SOFTWARE_SECURE"][ "RSA_PUBLIC_KEY"] rsa_encrypted_aes_key = rsa_encrypt(aes_key, rsa_key_str) # Upload this to S3 s3_key = self._generate_s3_key("photo_id") s3_key.set_contents_from_string(encrypt_and_encode(img_data, aes_key)) # Update our record fields self.photo_id_key = rsa_encrypted_aes_key.encode('base64') self.save()
def upload_photo_id_image(self, img_data): """ Upload an the user's photo ID image to S3. `img_data` should be a raw bytestream of a PNG image. This method will take the data, encrypt it using a randomly generated AES key, encode it with base64 and save it to S3. The random key is also encrypted using Software Secure's public RSA key and stored in our `photo_id_key` field. Yes, encoding it to base64 adds compute and disk usage without much real benefit, but that's what the other end of this API is expecting to get. """ # Skip this whole thing if we're running acceptance tests or if we're # developing and aren't interested in working on student identity # verification functionality. If you do want to work on it, you have to # explicitly enable these in your private settings. if settings.FEATURES.get('AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING'): return aes_key = random_aes_key() rsa_key_str = settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["RSA_PUBLIC_KEY"] rsa_encrypted_aes_key = rsa_encrypt(aes_key, rsa_key_str) # Upload this to S3 s3_key = self._generate_s3_key("photo_id") s3_key.set_contents_from_string(encrypt_and_encode(img_data, aes_key)) # Update our record fields self.photo_id_key = rsa_encrypted_aes_key.encode('base64') self.save()
def upload_photo_id_image(self, img_data): aes_key = random_aes_key() rsa_key_str = settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["RSA_PUBLIC_KEY"] rsa_encrypted_aes_key = rsa_encrypt(aes_key, rsa_key_str) # Upload this to S3 s3_key = self._generate_key("photo_id") s3_key.set_contents_from_string(encrypt_and_encode(img_data, aes_key)) # Update our record fields self.photo_id_key = rsa_encrypted_aes_key.encode('base64') self.save()
def _encrypted_user_photo_key_str(self): """ Software Secure needs to have both UserPhoto and PhotoID decrypted in the same manner. So even though this is going to be the same for every request, we're also using RSA encryption to encrypt the AES key for faces. """ face_aes_key_str = settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["FACE_IMAGE_AES_KEY"] face_aes_key = face_aes_key_str.decode("hex") rsa_key_str = settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["RSA_PUBLIC_KEY"] rsa_encrypted_face_aes_key = rsa_encrypt(face_aes_key, rsa_key_str) return rsa_encrypted_face_aes_key.encode("base64")
def test_rsa(): # Make up some garbage keys for testing purposes. pub_key_str = """-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1hLVjP0oV0Uy/+jQ+Upz c+eYc4Pyflb/WpfgYATggkoQdnsdplmvPtQr85+utgqKPxOh+PvYGW8QNUzjLIu4 5/GlmvBa82i1jRMgEAxGI95bz7j9DtH+7mnj+06zR5xHwT49jK0zMs5MjMaz5WRq BUNkz7dxWzDrYJZQx230sPp6upy1Y5H5O8SnJVdghsh8sNciS4Bo4ZONQ3giBwxz h5svjspz1MIsOoShjbAdfG+4VX7sVwYlw2rnQeRsMH5/xpnNeqtScyOMoz0N9UDG dtRMNGa2MihAg7zh7/zckbUrtf+o5wQtlCJL1Kdj4EjshqYvCxzWnSM+MaYAjb3M EQIDAQAB -----END PUBLIC KEY-----""" priv_key_str = """-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA1hLVjP0oV0Uy/+jQ+Upzc+eYc4Pyflb/WpfgYATggkoQdnsd plmvPtQr85+utgqKPxOh+PvYGW8QNUzjLIu45/GlmvBa82i1jRMgEAxGI95bz7j9 DtH+7mnj+06zR5xHwT49jK0zMs5MjMaz5WRqBUNkz7dxWzDrYJZQx230sPp6upy1 Y5H5O8SnJVdghsh8sNciS4Bo4ZONQ3giBwxzh5svjspz1MIsOoShjbAdfG+4VX7s VwYlw2rnQeRsMH5/xpnNeqtScyOMoz0N9UDGdtRMNGa2MihAg7zh7/zckbUrtf+o 5wQtlCJL1Kdj4EjshqYvCxzWnSM+MaYAjb3MEQIDAQABAoIBAQCviuA87fdfoOoS OerrEacc20QDLaby/QoGUtZ2RmmHzY40af7FQ3PWFIw6Ca5trrTwxnuivXnWWWG0 I2mCRM0Kvfgr1n7ubOW7WnyHTFlT3mnxK2Ov/HmNLZ36nO2cgkXA6/Xy3rBGMC9L nUE1kSLzT/Fh965ntfS9zmVNNBhb6no0rVkGx5nK3vTI6kUmaa0m+E7KL/HweO4c JodhN8CX4gpxSrkuwJ7IHEPYspqc0jInMYKLmD3d2g3BiOctjzFmaj3lV5AUlujW z7/LVe5WAEaaxjwaMvwqrJLv9ogxWU3etJf22+Yy7r5gbPtqpqJrCZ5+WpGnUHws 3mMGP2QBAoGBAOc3pzLFgGUREVPSFQlJ06QFtfKYqg9fFHJCgWu/2B2aVZc2aO/t Zhuoz+AgOdzsw+CWv7K0FH9sUkffk2VKPzwwwufLK3avD9gI0bhmBAYvdhS6A3nO YM3W+lvmaJtFL00K6kdd+CzgRnBS9cZ70WbcbtqjdXI6+mV1WdGUTLhBAoGBAO0E xhD4z+GjubSgfHYEZPgRJPqyUIfDH+5UmFGpr6zlvNN/depaGxsbhW8t/V6xkxsG MCgic7GLMihEiUMx1+/snVs5bBUx7OT9API0d+vStHCFlTTe6aTdmiduFD4PbDsq 6E4DElVRqZhpIYusdDh7Z3fO2hm5ad4FfMlx65/RAoGAPYEfV7ETs06z9kEG2X6q 7pGaUZrsecRH8xDfzmKswUshg2S0y0WyCJ+CFFNeMPdGL4LKIWYnobGVvYqqcaIr af5qijAQMrTkmQnXh56TaXXMijzk2czdEUQjOrjykIL5zxudMDi94GoUMqLOv+qF zD/MuRoMDsPDgaOSrd4t/kECgYEAzwBNT8NOIz3P0Z4cNSJPYIvwpPaY+IkE2SyO vzuYj0Mx7/Ew9ZTueXVGyzv6PfqOhJqZ8mNscZIlIyAAVWwxsHwRTfvPlo882xzP 97i1R4OFTYSNNFi+69sSZ/9utGjZ2K73pjJuj487tD2VK5xZAH9edTd2KeNSP7LB MlpJNBECgYAmIswPdldm+G8SJd5j9O2fcDVTURjKAoSXCv2j4gEZzzfudpLWNHYu l8N6+LEIVTMAytPk+/bImHvGHKZkCz5rEMSuYJWOmqKI92rUtI6fz5DUb3XSbrwT 3W+sdGFUK3GH1NAX71VxbAlFVLUetcMwai1+wXmGkRw6A7YezVFnhw== -----END RSA PRIVATE KEY-----""" aes_key_str = "32fe72aaf2abb44de9e161131b5435c8d37cbdb6f5df242ae860b283115f2dae" aes_key = aes_key_str.decode('hex') encrypted_aes_key = rsa_encrypt(aes_key, pub_key_str) assert_equals(aes_key, rsa_decrypt(encrypted_aes_key, priv_key_str)) # Even though our AES key is only 32 bytes, RSA encryption will make it 256 # bytes, and base64 encoding will blow that up to 344 assert_equals(len(base64.urlsafe_b64encode(encrypted_aes_key)), 344)