<commit_before>import hashlib

import nacl.secret
import nacl.utils
import six
from nacl.exceptions import CryptoError
from polymorphic.models import PolymorphicModel

from django.conf import settings
from django.contrib.sites.models import Site
from django.core.mail.message import EmailMultiAlternatives
from django.db import models
from django.template import Context, Template
from django.utils import timezone
from django.utils.crypto import get_random_string, pbkdf2
from django.utils.html import strip_tags


def _encrypt_report(salt, key, report_text):
    """Encrypts a report using the given secret key & salt. The secret key is stretched to 32 bytes using Django's
    PBKDF2+SHA256 implementation. The encryption uses PyNacl & Salsa20 stream cipher.

    Args:
      salt (str): cryptographic salt
      key (str): secret key
      report_text (str): full report as a string

    Returns:
      bytes: the encrypted bytes of the report

    """
    stretched_key = pbkdf2(key, salt, settings.KEY_ITERATIONS, digest=hashlib.sha256)
    box = nacl.secret.SecretBox(stretched_key)
    message = report_text.encode('utf-8')
    nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
    return box.encrypt(message, nonce)


def _decrypt_report(salt, key, encrypted):
    """Decrypts an encrypted report.

    Args:
      salt (str): cryptographic salt
      key (str): secret key
      encrypted (bytes): full report encrypted

    Returns:
      str: the decrypted report as a string

    Raises:
      CryptoError: If the key and salt fail to decrypt the record.

    """
    stretched_key = pbkdf2(key, salt, settings.KEY_ITERATIONS, digest=hashlib.sha256)
    box = nacl.secret.SecretBox(stretched_key)
    decrypted = box.decrypt(bytes(encrypted))
    return decrypted.decode('utf-8')


def _pepper(encrypted_report):
    """Uses a secret value stored on the server to encrypt an already hashed report, to add protection if the database
    is breached but the server is not. Requires settings.PEPPER to be set to a 32 byte value. In production, this value
    should be set via environment parameter. Uses PyNacl's Salsa20 stream cipher.

    Args:
      encrypted_report (bytes): the encrypted report

    Returns:
      bytes: a further encrypted report

    """
    pepper = settings.PEPPER
    box = nacl.secret.SecretBox(pepper)
    nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
    return box.encrypt(encrypted_report, nonce)


def _unpepper(peppered_report):
    """Decrypts a report that has been peppered with the _pepper method. Requires settings.PEPPER to be set to a 32
    byte value. In production, this value should be set via environment parameter.

    Args:
      peppered_report(bytes): a report that has been encrypted using a secret key then encrypted using the pepper

    Returns:
      bytes: the report, still encrypted with the secret key

    Raises:
      CryptoError: If the pepper fails to decrypt the record.
    """
    pepper = settings.PEPPER
    box = nacl.secret.SecretBox(pepper)
    decrypted = box.decrypt(peppered_report)
    return decrypted


class Report(models.Model):
    """The full text of a reported incident."""
    encrypted = models.BinaryField(blank=False)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)
    added = models.DateTimeField(auto_now_add=True)
    last_edited = models.DateTimeField(blank=True, null=True)
    salt = models.CharField(blank=False, max_length=256)
<commit_msg>force bytes in pepper method<commit_after>import hashlib

import nacl.secret
import nacl.utils
import six
from nacl.exceptions import CryptoError
from polymorphic.models import PolymorphicModel

from django.conf import settings
from django.contrib.sites.models import Site
from django.core.mail.message import EmailMultiAlternatives
from django.db import models
from django.template import Context, Template
from django.utils import timezone
from django.utils.crypto import get_random_string, pbkdf2
from django.utils.html import strip_tags


def _encrypt_report(salt, key, report_text):
    """Encrypts a report using the given secret key & salt. The secret key is stretched to 32 bytes using Django's
    PBKDF2+SHA256 implementation. The encryption uses PyNacl & Salsa20 stream cipher.

    Args:
      salt (str): cryptographic salt
      key (str): secret key
      report_text (str): full report as a string

    Returns:
      bytes: the encrypted bytes of the report

    """
    stretched_key = pbkdf2(key, salt, settings.KEY_ITERATIONS, digest=hashlib.sha256)
    box = nacl.secret.SecretBox(stretched_key)
    message = report_text.encode('utf-8')
    nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
    return box.encrypt(message, nonce)


def _decrypt_report(salt, key, encrypted):
    """Decrypts an encrypted report.

    Args:
      salt (str): cryptographic salt
      key (str): secret key
      encrypted (bytes): full report encrypted

    Returns:
      str: the decrypted report as a string

    Raises:
      CryptoError: If the key and salt fail to decrypt the record.

    """
    stretched_key = pbkdf2(key, salt, settings.KEY_ITERATIONS, digest=hashlib.sha256)
    box = nacl.secret.SecretBox(stretched_key)
    decrypted = box.decrypt(bytes(encrypted))  # need to force to bytes bc BinaryField can return as memoryview
    return decrypted.decode('utf-8')


def _pepper(encrypted_report):
    """Uses a secret value stored on the server to encrypt an already hashed report, to add protection if the database
    is breached but the server is not. Requires settings.PEPPER to be set to a 32 byte value. In production, this value
    should be set via environment parameter. Uses PyNacl's Salsa20 stream cipher.

    Args:
      encrypted_report (bytes): the encrypted report

    Returns:
      bytes: a further encrypted report

    """
    pepper = settings.PEPPER
    box = nacl.secret.SecretBox(pepper)
    nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
    return box.encrypt(encrypted_report, nonce)


def _unpepper(peppered_report):
    """Decrypts a report that has been peppered with the _pepper method. Requires settings.PEPPER to be set to a 32
    byte value. In production, this value should be set via environment parameter.

    Args:
      peppered_report(bytes): a report that has been encrypted using a secret key then encrypted using the pepper

    Returns:
      bytes: the report, still encrypted with the secret key

    Raises:
      CryptoError: If the pepper fails to decrypt the record.
    """
    pepper = settings.PEPPER
    box = nacl.secret.SecretBox(pepper)
    decrypted = box.decrypt(bytes(peppered_report))  # need to force to bytes bc BinaryField can return as memoryview
    return decrypted


class Report(models.Model):
    """The full text of a reported incident."""
    encrypted = models.BinaryField(blank=False)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)
    added = models.DateTimeField(auto_now_add=True)
    last_edited = models.DateTimeField(blank=True, null=True)
    salt = models.CharField(blank=False, max_length=256)

{'fraction_non_alphanumeric': 0.07251264755480608, 'fraction_numerical': 0.007869589657110737, 'mean_word_length': 3.7541750167000667, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4793886', 'n_tokens_mistral': 2171, 'n_tokens_neox': 2038, 'n_words': 720}