Simple one time pad cipher











up vote
3
down vote

favorite












I had this idea not to long ago on creating a secure chat for people who need to be not meddled with when talking (like whistleblowers, hackers, etc) talking to one of my friends about it he said I could use the One Time Pad Cipher, so I decided to write my own in Python.



If you don't know what the one time pad is, in a nutshell it's a cipher that generates a key for you that is as long as the string you pass to it, this key makes it theoretically impossible to crack the cipher without the key itself, due to their being so many possible combinations.



My cipher uses sqlite to store a database into memory to keep the keys unique, once the program is exited, the database is destroyed (theoretically). I would like someone to poke as many holes in this as possible, I would like to see if the string is possible to be cracked and would also like someone to break the database if possible. Basically I want to know how secure this is. Please keep in mind, this is not a finished product but just a fundamental understanding to a larger project. So critique away and have fun with it, thank you!



The code:



import random
import string
import sqlite3


PUNC = string.punctuation
ALPHABET = string.ascii_letters


def initialize():
"""
initialize the database into memory so that it can be wiped upon exit
"""
connection = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
cursor = connection.cursor()
cursor.execute(
"CREATE TABLE used_keys ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"key TEXT"
")"
)
return cursor


def create_key(_string, db_cursor):
"""
create the key from a provided string
"""
retval = ""
set_string = ""
used_keys = db_cursor.execute("SELECT key FROM used_keys")
id_number = len(used_keys.fetchall()) + 1
for c in _string:
if c in PUNC:
c = ""
if c == " " or c.isspace():
c = ""
set_string += c
key_length = len(set_string)
acceptable_key_characters = string.ascii_letters
for _ in range(key_length):
retval += random.choice(acceptable_key_characters)
if retval not in used_keys:
db_cursor.execute("INSERT INTO used_keys(id, key) VALUES (?, ?)", (id_number, retval))
return retval, set_string
else:
create_key(_string, db_cursor)


def encode_cipher(_string, key):
"""
encode the string using a generated unique key
"""
retval = ""
for k, v in zip(_string, key):
c_index = ALPHABET.index(k)
key_index = ALPHABET.index(v)
cipher_index = c_index + key_index
try:
retval += ALPHABET[cipher_index]
except IndexError:
cipher_index -= 26
retval += ALPHABET[cipher_index]
return retval


def decode_cipher(encoded, key):
"""
decode the encoded string using the encoded string and the key used to cipher it
"""
retval = ""
for k, v in zip(encoded, key):
c_index = ALPHABET.index(k)
key_index = ALPHABET.index(v)
decode = c_index - key_index
try:
retval += ALPHABET[decode]
except IndexError:
decode += 26
retval += ALPHABET[decode]
return retval


def main():
"""
main messy function
"""
exited = False
choices = {"1": "show keys", "2": "create new key", "3": "decode a cipher", "4": "exit"}
cursor = initialize()
seperator = "-" * 35
print("database initialized, what would you like to do:")
try:
while not exited:
for item in sorted(choices.keys()):
print("[{}] {}".format(item, choices[item]))
choice = raw_input(">> ")
if choice == "1":
keys = cursor.execute("SELECT key FROM used_keys")
print(seperator)
for key in keys.fetchall():
print(key[0])
print(seperator)
elif choice == "2":
phrase = raw_input("Enter your secret phrase: ")
key, set_string = create_key(phrase, cursor)
encoded = encode_cipher(set_string, key)
print(seperator)
print("encoded message: '{}'".format(encoded))
print(seperator)
elif choice == "3":
encoded_cipher = raw_input("enter and encoded cipher: ")
encode_key = raw_input("enter the cipher key: ")
decoded = decode_cipher(encoded_cipher, encode_key)
print(seperator)
print("decoded message: '{}'".format(decoded))
print(seperator)
elif choice == "4":
print("database destroyed")
exited = True
except KeyboardInterrupt:
print("database has been destroyed")


if __name__ == "__main__":
main()









share|improve this question

















This question has an open bounty worth +50
reputation from 13aal ending in 4 days.


This question has not received enough attention.




















    up vote
    3
    down vote

    favorite












    I had this idea not to long ago on creating a secure chat for people who need to be not meddled with when talking (like whistleblowers, hackers, etc) talking to one of my friends about it he said I could use the One Time Pad Cipher, so I decided to write my own in Python.



    If you don't know what the one time pad is, in a nutshell it's a cipher that generates a key for you that is as long as the string you pass to it, this key makes it theoretically impossible to crack the cipher without the key itself, due to their being so many possible combinations.



    My cipher uses sqlite to store a database into memory to keep the keys unique, once the program is exited, the database is destroyed (theoretically). I would like someone to poke as many holes in this as possible, I would like to see if the string is possible to be cracked and would also like someone to break the database if possible. Basically I want to know how secure this is. Please keep in mind, this is not a finished product but just a fundamental understanding to a larger project. So critique away and have fun with it, thank you!



    The code:



    import random
    import string
    import sqlite3


    PUNC = string.punctuation
    ALPHABET = string.ascii_letters


    def initialize():
    """
    initialize the database into memory so that it can be wiped upon exit
    """
    connection = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
    cursor = connection.cursor()
    cursor.execute(
    "CREATE TABLE used_keys ("
    "id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "key TEXT"
    ")"
    )
    return cursor


    def create_key(_string, db_cursor):
    """
    create the key from a provided string
    """
    retval = ""
    set_string = ""
    used_keys = db_cursor.execute("SELECT key FROM used_keys")
    id_number = len(used_keys.fetchall()) + 1
    for c in _string:
    if c in PUNC:
    c = ""
    if c == " " or c.isspace():
    c = ""
    set_string += c
    key_length = len(set_string)
    acceptable_key_characters = string.ascii_letters
    for _ in range(key_length):
    retval += random.choice(acceptable_key_characters)
    if retval not in used_keys:
    db_cursor.execute("INSERT INTO used_keys(id, key) VALUES (?, ?)", (id_number, retval))
    return retval, set_string
    else:
    create_key(_string, db_cursor)


    def encode_cipher(_string, key):
    """
    encode the string using a generated unique key
    """
    retval = ""
    for k, v in zip(_string, key):
    c_index = ALPHABET.index(k)
    key_index = ALPHABET.index(v)
    cipher_index = c_index + key_index
    try:
    retval += ALPHABET[cipher_index]
    except IndexError:
    cipher_index -= 26
    retval += ALPHABET[cipher_index]
    return retval


    def decode_cipher(encoded, key):
    """
    decode the encoded string using the encoded string and the key used to cipher it
    """
    retval = ""
    for k, v in zip(encoded, key):
    c_index = ALPHABET.index(k)
    key_index = ALPHABET.index(v)
    decode = c_index - key_index
    try:
    retval += ALPHABET[decode]
    except IndexError:
    decode += 26
    retval += ALPHABET[decode]
    return retval


    def main():
    """
    main messy function
    """
    exited = False
    choices = {"1": "show keys", "2": "create new key", "3": "decode a cipher", "4": "exit"}
    cursor = initialize()
    seperator = "-" * 35
    print("database initialized, what would you like to do:")
    try:
    while not exited:
    for item in sorted(choices.keys()):
    print("[{}] {}".format(item, choices[item]))
    choice = raw_input(">> ")
    if choice == "1":
    keys = cursor.execute("SELECT key FROM used_keys")
    print(seperator)
    for key in keys.fetchall():
    print(key[0])
    print(seperator)
    elif choice == "2":
    phrase = raw_input("Enter your secret phrase: ")
    key, set_string = create_key(phrase, cursor)
    encoded = encode_cipher(set_string, key)
    print(seperator)
    print("encoded message: '{}'".format(encoded))
    print(seperator)
    elif choice == "3":
    encoded_cipher = raw_input("enter and encoded cipher: ")
    encode_key = raw_input("enter the cipher key: ")
    decoded = decode_cipher(encoded_cipher, encode_key)
    print(seperator)
    print("decoded message: '{}'".format(decoded))
    print(seperator)
    elif choice == "4":
    print("database destroyed")
    exited = True
    except KeyboardInterrupt:
    print("database has been destroyed")


    if __name__ == "__main__":
    main()









    share|improve this question

















    This question has an open bounty worth +50
    reputation from 13aal ending in 4 days.


    This question has not received enough attention.


















      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      I had this idea not to long ago on creating a secure chat for people who need to be not meddled with when talking (like whistleblowers, hackers, etc) talking to one of my friends about it he said I could use the One Time Pad Cipher, so I decided to write my own in Python.



      If you don't know what the one time pad is, in a nutshell it's a cipher that generates a key for you that is as long as the string you pass to it, this key makes it theoretically impossible to crack the cipher without the key itself, due to their being so many possible combinations.



      My cipher uses sqlite to store a database into memory to keep the keys unique, once the program is exited, the database is destroyed (theoretically). I would like someone to poke as many holes in this as possible, I would like to see if the string is possible to be cracked and would also like someone to break the database if possible. Basically I want to know how secure this is. Please keep in mind, this is not a finished product but just a fundamental understanding to a larger project. So critique away and have fun with it, thank you!



      The code:



      import random
      import string
      import sqlite3


      PUNC = string.punctuation
      ALPHABET = string.ascii_letters


      def initialize():
      """
      initialize the database into memory so that it can be wiped upon exit
      """
      connection = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
      cursor = connection.cursor()
      cursor.execute(
      "CREATE TABLE used_keys ("
      "id INTEGER PRIMARY KEY AUTOINCREMENT,"
      "key TEXT"
      ")"
      )
      return cursor


      def create_key(_string, db_cursor):
      """
      create the key from a provided string
      """
      retval = ""
      set_string = ""
      used_keys = db_cursor.execute("SELECT key FROM used_keys")
      id_number = len(used_keys.fetchall()) + 1
      for c in _string:
      if c in PUNC:
      c = ""
      if c == " " or c.isspace():
      c = ""
      set_string += c
      key_length = len(set_string)
      acceptable_key_characters = string.ascii_letters
      for _ in range(key_length):
      retval += random.choice(acceptable_key_characters)
      if retval not in used_keys:
      db_cursor.execute("INSERT INTO used_keys(id, key) VALUES (?, ?)", (id_number, retval))
      return retval, set_string
      else:
      create_key(_string, db_cursor)


      def encode_cipher(_string, key):
      """
      encode the string using a generated unique key
      """
      retval = ""
      for k, v in zip(_string, key):
      c_index = ALPHABET.index(k)
      key_index = ALPHABET.index(v)
      cipher_index = c_index + key_index
      try:
      retval += ALPHABET[cipher_index]
      except IndexError:
      cipher_index -= 26
      retval += ALPHABET[cipher_index]
      return retval


      def decode_cipher(encoded, key):
      """
      decode the encoded string using the encoded string and the key used to cipher it
      """
      retval = ""
      for k, v in zip(encoded, key):
      c_index = ALPHABET.index(k)
      key_index = ALPHABET.index(v)
      decode = c_index - key_index
      try:
      retval += ALPHABET[decode]
      except IndexError:
      decode += 26
      retval += ALPHABET[decode]
      return retval


      def main():
      """
      main messy function
      """
      exited = False
      choices = {"1": "show keys", "2": "create new key", "3": "decode a cipher", "4": "exit"}
      cursor = initialize()
      seperator = "-" * 35
      print("database initialized, what would you like to do:")
      try:
      while not exited:
      for item in sorted(choices.keys()):
      print("[{}] {}".format(item, choices[item]))
      choice = raw_input(">> ")
      if choice == "1":
      keys = cursor.execute("SELECT key FROM used_keys")
      print(seperator)
      for key in keys.fetchall():
      print(key[0])
      print(seperator)
      elif choice == "2":
      phrase = raw_input("Enter your secret phrase: ")
      key, set_string = create_key(phrase, cursor)
      encoded = encode_cipher(set_string, key)
      print(seperator)
      print("encoded message: '{}'".format(encoded))
      print(seperator)
      elif choice == "3":
      encoded_cipher = raw_input("enter and encoded cipher: ")
      encode_key = raw_input("enter the cipher key: ")
      decoded = decode_cipher(encoded_cipher, encode_key)
      print(seperator)
      print("decoded message: '{}'".format(decoded))
      print(seperator)
      elif choice == "4":
      print("database destroyed")
      exited = True
      except KeyboardInterrupt:
      print("database has been destroyed")


      if __name__ == "__main__":
      main()









      share|improve this question















      I had this idea not to long ago on creating a secure chat for people who need to be not meddled with when talking (like whistleblowers, hackers, etc) talking to one of my friends about it he said I could use the One Time Pad Cipher, so I decided to write my own in Python.



      If you don't know what the one time pad is, in a nutshell it's a cipher that generates a key for you that is as long as the string you pass to it, this key makes it theoretically impossible to crack the cipher without the key itself, due to their being so many possible combinations.



      My cipher uses sqlite to store a database into memory to keep the keys unique, once the program is exited, the database is destroyed (theoretically). I would like someone to poke as many holes in this as possible, I would like to see if the string is possible to be cracked and would also like someone to break the database if possible. Basically I want to know how secure this is. Please keep in mind, this is not a finished product but just a fundamental understanding to a larger project. So critique away and have fun with it, thank you!



      The code:



      import random
      import string
      import sqlite3


      PUNC = string.punctuation
      ALPHABET = string.ascii_letters


      def initialize():
      """
      initialize the database into memory so that it can be wiped upon exit
      """
      connection = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
      cursor = connection.cursor()
      cursor.execute(
      "CREATE TABLE used_keys ("
      "id INTEGER PRIMARY KEY AUTOINCREMENT,"
      "key TEXT"
      ")"
      )
      return cursor


      def create_key(_string, db_cursor):
      """
      create the key from a provided string
      """
      retval = ""
      set_string = ""
      used_keys = db_cursor.execute("SELECT key FROM used_keys")
      id_number = len(used_keys.fetchall()) + 1
      for c in _string:
      if c in PUNC:
      c = ""
      if c == " " or c.isspace():
      c = ""
      set_string += c
      key_length = len(set_string)
      acceptable_key_characters = string.ascii_letters
      for _ in range(key_length):
      retval += random.choice(acceptable_key_characters)
      if retval not in used_keys:
      db_cursor.execute("INSERT INTO used_keys(id, key) VALUES (?, ?)", (id_number, retval))
      return retval, set_string
      else:
      create_key(_string, db_cursor)


      def encode_cipher(_string, key):
      """
      encode the string using a generated unique key
      """
      retval = ""
      for k, v in zip(_string, key):
      c_index = ALPHABET.index(k)
      key_index = ALPHABET.index(v)
      cipher_index = c_index + key_index
      try:
      retval += ALPHABET[cipher_index]
      except IndexError:
      cipher_index -= 26
      retval += ALPHABET[cipher_index]
      return retval


      def decode_cipher(encoded, key):
      """
      decode the encoded string using the encoded string and the key used to cipher it
      """
      retval = ""
      for k, v in zip(encoded, key):
      c_index = ALPHABET.index(k)
      key_index = ALPHABET.index(v)
      decode = c_index - key_index
      try:
      retval += ALPHABET[decode]
      except IndexError:
      decode += 26
      retval += ALPHABET[decode]
      return retval


      def main():
      """
      main messy function
      """
      exited = False
      choices = {"1": "show keys", "2": "create new key", "3": "decode a cipher", "4": "exit"}
      cursor = initialize()
      seperator = "-" * 35
      print("database initialized, what would you like to do:")
      try:
      while not exited:
      for item in sorted(choices.keys()):
      print("[{}] {}".format(item, choices[item]))
      choice = raw_input(">> ")
      if choice == "1":
      keys = cursor.execute("SELECT key FROM used_keys")
      print(seperator)
      for key in keys.fetchall():
      print(key[0])
      print(seperator)
      elif choice == "2":
      phrase = raw_input("Enter your secret phrase: ")
      key, set_string = create_key(phrase, cursor)
      encoded = encode_cipher(set_string, key)
      print(seperator)
      print("encoded message: '{}'".format(encoded))
      print(seperator)
      elif choice == "3":
      encoded_cipher = raw_input("enter and encoded cipher: ")
      encode_key = raw_input("enter the cipher key: ")
      decoded = decode_cipher(encoded_cipher, encode_key)
      print(seperator)
      print("decoded message: '{}'".format(decoded))
      print(seperator)
      elif choice == "4":
      print("database destroyed")
      exited = True
      except KeyboardInterrupt:
      print("database has been destroyed")


      if __name__ == "__main__":
      main()






      python python-2.x security sqlite caesar-cipher






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 13 at 14:22

























      asked Nov 12 at 22:48









      13aal

      161227




      161227






      This question has an open bounty worth +50
      reputation from 13aal ending in 4 days.


      This question has not received enough attention.








      This question has an open bounty worth +50
      reputation from 13aal ending in 4 days.


      This question has not received enough attention.
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          2
          down vote













          The hard problems for one-time pads are




          1. randomly generating the pad, and

          2. securely sharing the pad between the participants (and nobody else).


          The first problem is not solved, because the random package is a pseudo-random generator - it can't produce enough randomness for this purpose. We'd need a true random number generator, which (in general) requires a hardware source of randomness. Deterministic arithmetic is not a good source of crypto-grade randomness.



          The second problem doesn't appear to be solved - to my understanding, we store the OTP, but don't distribute it, so the only way to decode a message is by returning it to the place where it was encoded. This might work for transmission across time (i.e. storage), but it's unsuitable for transmission over distance (i.e. communication).






          share|improve this answer





















          • Isn't PyCrypto's random number generator acceptable to use?
            – 13aal
            Nov 13 at 15:30










          • Also couldn't I theoretically just use the os.urandom call for a cryptographically secure number?
            – 13aal
            Nov 13 at 15:31






          • 2




            That's a better source. In Python 3.6 onwards, consider secrets.SystemRandom.
            – Toby Speight
            Nov 13 at 16:08










          • Hey, just letting you know in python 2.7 you can use random.SystemRandom()
            – 13aal
            Nov 14 at 15:45


















          up vote
          1
          down vote













          Your plaintext, ciphertext and key all just alphabets, it is not difficult(or just say easy) for bruteforce, only need 56 ** length



          Why not using bytes crack difficult will raise up to 256 ** length



          And you can use base64 for user friendly ciphertext/key output.



          create_key



          You can use os.urandom to generate random bytes as OTP key, and no need for filter input strings, as they can all be encrypted



          def create_key(_string, db_cursor):
          ...
          retval = base64.b64encode(os.urandom(len(_string)))
          ...


          encode_cipher



          def encode_cipher(_string, key):
          key = base64.b64decode(key)
          retval = ""
          for k, v in zip(_string, key):
          retval += chr(ord(k) ^ ord(v))
          return base64.b64encode(retval)


          decode_cipher



          def decode_cipher(encoded, key):
          retval = ""
          encoded = base64.b64decode(encoded)
          key = base64.b64decode(key)
          for k, v in zip(encoded, key):
          retval += chr(ord(k) ^ ord(v))
          return retval





          share|improve this answer























          • The base64 defeats the purpose of a one time pad. Also its not possible to get the string without the key, you can try to bruteforce it if you want to, you may or may not get the correct output try it with this one: zLFREvoTtPM. I see no proof that the original string can be bruteforced without the key itself.
            – 13aal
            2 days ago












          • It is meaningless to crack a random message with length just 11 and encrypted by OTP. Think of such a threat mode, the hacker know 2 mins ago you send your friend and an important encryped file, and you also send him the password encrypted using OTP, then hacker just need to crack messages around 2 mins ago and try to decrypt that file to verify it. And I don't get why base64 defeat the purpose of OTP, it is just encoding nothing with encryption.
            – Aries_is_there
            2 days ago










          • Yes OTP is an highly safe encrypt way, it is quite difficult to crack all or any random ciphertexts. I suggest using bytes instead of just alphabets just for let it be more difficult to crack. and the key isn't something like here bank use, user can only input numbers (and you limit it to alphabets here), why not let it be more choice and be more tough for hackers
            – Aries_is_there
            2 days ago











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207515%2fsimple-one-time-pad-cipher%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          2
          down vote













          The hard problems for one-time pads are




          1. randomly generating the pad, and

          2. securely sharing the pad between the participants (and nobody else).


          The first problem is not solved, because the random package is a pseudo-random generator - it can't produce enough randomness for this purpose. We'd need a true random number generator, which (in general) requires a hardware source of randomness. Deterministic arithmetic is not a good source of crypto-grade randomness.



          The second problem doesn't appear to be solved - to my understanding, we store the OTP, but don't distribute it, so the only way to decode a message is by returning it to the place where it was encoded. This might work for transmission across time (i.e. storage), but it's unsuitable for transmission over distance (i.e. communication).






          share|improve this answer





















          • Isn't PyCrypto's random number generator acceptable to use?
            – 13aal
            Nov 13 at 15:30










          • Also couldn't I theoretically just use the os.urandom call for a cryptographically secure number?
            – 13aal
            Nov 13 at 15:31






          • 2




            That's a better source. In Python 3.6 onwards, consider secrets.SystemRandom.
            – Toby Speight
            Nov 13 at 16:08










          • Hey, just letting you know in python 2.7 you can use random.SystemRandom()
            – 13aal
            Nov 14 at 15:45















          up vote
          2
          down vote













          The hard problems for one-time pads are




          1. randomly generating the pad, and

          2. securely sharing the pad between the participants (and nobody else).


          The first problem is not solved, because the random package is a pseudo-random generator - it can't produce enough randomness for this purpose. We'd need a true random number generator, which (in general) requires a hardware source of randomness. Deterministic arithmetic is not a good source of crypto-grade randomness.



          The second problem doesn't appear to be solved - to my understanding, we store the OTP, but don't distribute it, so the only way to decode a message is by returning it to the place where it was encoded. This might work for transmission across time (i.e. storage), but it's unsuitable for transmission over distance (i.e. communication).






          share|improve this answer





















          • Isn't PyCrypto's random number generator acceptable to use?
            – 13aal
            Nov 13 at 15:30










          • Also couldn't I theoretically just use the os.urandom call for a cryptographically secure number?
            – 13aal
            Nov 13 at 15:31






          • 2




            That's a better source. In Python 3.6 onwards, consider secrets.SystemRandom.
            – Toby Speight
            Nov 13 at 16:08










          • Hey, just letting you know in python 2.7 you can use random.SystemRandom()
            – 13aal
            Nov 14 at 15:45













          up vote
          2
          down vote










          up vote
          2
          down vote









          The hard problems for one-time pads are




          1. randomly generating the pad, and

          2. securely sharing the pad between the participants (and nobody else).


          The first problem is not solved, because the random package is a pseudo-random generator - it can't produce enough randomness for this purpose. We'd need a true random number generator, which (in general) requires a hardware source of randomness. Deterministic arithmetic is not a good source of crypto-grade randomness.



          The second problem doesn't appear to be solved - to my understanding, we store the OTP, but don't distribute it, so the only way to decode a message is by returning it to the place where it was encoded. This might work for transmission across time (i.e. storage), but it's unsuitable for transmission over distance (i.e. communication).






          share|improve this answer












          The hard problems for one-time pads are




          1. randomly generating the pad, and

          2. securely sharing the pad between the participants (and nobody else).


          The first problem is not solved, because the random package is a pseudo-random generator - it can't produce enough randomness for this purpose. We'd need a true random number generator, which (in general) requires a hardware source of randomness. Deterministic arithmetic is not a good source of crypto-grade randomness.



          The second problem doesn't appear to be solved - to my understanding, we store the OTP, but don't distribute it, so the only way to decode a message is by returning it to the place where it was encoded. This might work for transmission across time (i.e. storage), but it's unsuitable for transmission over distance (i.e. communication).







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 13 at 15:12









          Toby Speight

          22.4k537109




          22.4k537109












          • Isn't PyCrypto's random number generator acceptable to use?
            – 13aal
            Nov 13 at 15:30










          • Also couldn't I theoretically just use the os.urandom call for a cryptographically secure number?
            – 13aal
            Nov 13 at 15:31






          • 2




            That's a better source. In Python 3.6 onwards, consider secrets.SystemRandom.
            – Toby Speight
            Nov 13 at 16:08










          • Hey, just letting you know in python 2.7 you can use random.SystemRandom()
            – 13aal
            Nov 14 at 15:45


















          • Isn't PyCrypto's random number generator acceptable to use?
            – 13aal
            Nov 13 at 15:30










          • Also couldn't I theoretically just use the os.urandom call for a cryptographically secure number?
            – 13aal
            Nov 13 at 15:31






          • 2




            That's a better source. In Python 3.6 onwards, consider secrets.SystemRandom.
            – Toby Speight
            Nov 13 at 16:08










          • Hey, just letting you know in python 2.7 you can use random.SystemRandom()
            – 13aal
            Nov 14 at 15:45
















          Isn't PyCrypto's random number generator acceptable to use?
          – 13aal
          Nov 13 at 15:30




          Isn't PyCrypto's random number generator acceptable to use?
          – 13aal
          Nov 13 at 15:30












          Also couldn't I theoretically just use the os.urandom call for a cryptographically secure number?
          – 13aal
          Nov 13 at 15:31




          Also couldn't I theoretically just use the os.urandom call for a cryptographically secure number?
          – 13aal
          Nov 13 at 15:31




          2




          2




          That's a better source. In Python 3.6 onwards, consider secrets.SystemRandom.
          – Toby Speight
          Nov 13 at 16:08




          That's a better source. In Python 3.6 onwards, consider secrets.SystemRandom.
          – Toby Speight
          Nov 13 at 16:08












          Hey, just letting you know in python 2.7 you can use random.SystemRandom()
          – 13aal
          Nov 14 at 15:45




          Hey, just letting you know in python 2.7 you can use random.SystemRandom()
          – 13aal
          Nov 14 at 15:45












          up vote
          1
          down vote













          Your plaintext, ciphertext and key all just alphabets, it is not difficult(or just say easy) for bruteforce, only need 56 ** length



          Why not using bytes crack difficult will raise up to 256 ** length



          And you can use base64 for user friendly ciphertext/key output.



          create_key



          You can use os.urandom to generate random bytes as OTP key, and no need for filter input strings, as they can all be encrypted



          def create_key(_string, db_cursor):
          ...
          retval = base64.b64encode(os.urandom(len(_string)))
          ...


          encode_cipher



          def encode_cipher(_string, key):
          key = base64.b64decode(key)
          retval = ""
          for k, v in zip(_string, key):
          retval += chr(ord(k) ^ ord(v))
          return base64.b64encode(retval)


          decode_cipher



          def decode_cipher(encoded, key):
          retval = ""
          encoded = base64.b64decode(encoded)
          key = base64.b64decode(key)
          for k, v in zip(encoded, key):
          retval += chr(ord(k) ^ ord(v))
          return retval





          share|improve this answer























          • The base64 defeats the purpose of a one time pad. Also its not possible to get the string without the key, you can try to bruteforce it if you want to, you may or may not get the correct output try it with this one: zLFREvoTtPM. I see no proof that the original string can be bruteforced without the key itself.
            – 13aal
            2 days ago












          • It is meaningless to crack a random message with length just 11 and encrypted by OTP. Think of such a threat mode, the hacker know 2 mins ago you send your friend and an important encryped file, and you also send him the password encrypted using OTP, then hacker just need to crack messages around 2 mins ago and try to decrypt that file to verify it. And I don't get why base64 defeat the purpose of OTP, it is just encoding nothing with encryption.
            – Aries_is_there
            2 days ago










          • Yes OTP is an highly safe encrypt way, it is quite difficult to crack all or any random ciphertexts. I suggest using bytes instead of just alphabets just for let it be more difficult to crack. and the key isn't something like here bank use, user can only input numbers (and you limit it to alphabets here), why not let it be more choice and be more tough for hackers
            – Aries_is_there
            2 days ago















          up vote
          1
          down vote













          Your plaintext, ciphertext and key all just alphabets, it is not difficult(or just say easy) for bruteforce, only need 56 ** length



          Why not using bytes crack difficult will raise up to 256 ** length



          And you can use base64 for user friendly ciphertext/key output.



          create_key



          You can use os.urandom to generate random bytes as OTP key, and no need for filter input strings, as they can all be encrypted



          def create_key(_string, db_cursor):
          ...
          retval = base64.b64encode(os.urandom(len(_string)))
          ...


          encode_cipher



          def encode_cipher(_string, key):
          key = base64.b64decode(key)
          retval = ""
          for k, v in zip(_string, key):
          retval += chr(ord(k) ^ ord(v))
          return base64.b64encode(retval)


          decode_cipher



          def decode_cipher(encoded, key):
          retval = ""
          encoded = base64.b64decode(encoded)
          key = base64.b64decode(key)
          for k, v in zip(encoded, key):
          retval += chr(ord(k) ^ ord(v))
          return retval





          share|improve this answer























          • The base64 defeats the purpose of a one time pad. Also its not possible to get the string without the key, you can try to bruteforce it if you want to, you may or may not get the correct output try it with this one: zLFREvoTtPM. I see no proof that the original string can be bruteforced without the key itself.
            – 13aal
            2 days ago












          • It is meaningless to crack a random message with length just 11 and encrypted by OTP. Think of such a threat mode, the hacker know 2 mins ago you send your friend and an important encryped file, and you also send him the password encrypted using OTP, then hacker just need to crack messages around 2 mins ago and try to decrypt that file to verify it. And I don't get why base64 defeat the purpose of OTP, it is just encoding nothing with encryption.
            – Aries_is_there
            2 days ago










          • Yes OTP is an highly safe encrypt way, it is quite difficult to crack all or any random ciphertexts. I suggest using bytes instead of just alphabets just for let it be more difficult to crack. and the key isn't something like here bank use, user can only input numbers (and you limit it to alphabets here), why not let it be more choice and be more tough for hackers
            – Aries_is_there
            2 days ago













          up vote
          1
          down vote










          up vote
          1
          down vote









          Your plaintext, ciphertext and key all just alphabets, it is not difficult(or just say easy) for bruteforce, only need 56 ** length



          Why not using bytes crack difficult will raise up to 256 ** length



          And you can use base64 for user friendly ciphertext/key output.



          create_key



          You can use os.urandom to generate random bytes as OTP key, and no need for filter input strings, as they can all be encrypted



          def create_key(_string, db_cursor):
          ...
          retval = base64.b64encode(os.urandom(len(_string)))
          ...


          encode_cipher



          def encode_cipher(_string, key):
          key = base64.b64decode(key)
          retval = ""
          for k, v in zip(_string, key):
          retval += chr(ord(k) ^ ord(v))
          return base64.b64encode(retval)


          decode_cipher



          def decode_cipher(encoded, key):
          retval = ""
          encoded = base64.b64decode(encoded)
          key = base64.b64decode(key)
          for k, v in zip(encoded, key):
          retval += chr(ord(k) ^ ord(v))
          return retval





          share|improve this answer














          Your plaintext, ciphertext and key all just alphabets, it is not difficult(or just say easy) for bruteforce, only need 56 ** length



          Why not using bytes crack difficult will raise up to 256 ** length



          And you can use base64 for user friendly ciphertext/key output.



          create_key



          You can use os.urandom to generate random bytes as OTP key, and no need for filter input strings, as they can all be encrypted



          def create_key(_string, db_cursor):
          ...
          retval = base64.b64encode(os.urandom(len(_string)))
          ...


          encode_cipher



          def encode_cipher(_string, key):
          key = base64.b64decode(key)
          retval = ""
          for k, v in zip(_string, key):
          retval += chr(ord(k) ^ ord(v))
          return base64.b64encode(retval)


          decode_cipher



          def decode_cipher(encoded, key):
          retval = ""
          encoded = base64.b64decode(encoded)
          key = base64.b64decode(key)
          for k, v in zip(encoded, key):
          retval += chr(ord(k) ^ ord(v))
          return retval






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 2 days ago

























          answered 2 days ago









          Aries_is_there

          61529




          61529












          • The base64 defeats the purpose of a one time pad. Also its not possible to get the string without the key, you can try to bruteforce it if you want to, you may or may not get the correct output try it with this one: zLFREvoTtPM. I see no proof that the original string can be bruteforced without the key itself.
            – 13aal
            2 days ago












          • It is meaningless to crack a random message with length just 11 and encrypted by OTP. Think of such a threat mode, the hacker know 2 mins ago you send your friend and an important encryped file, and you also send him the password encrypted using OTP, then hacker just need to crack messages around 2 mins ago and try to decrypt that file to verify it. And I don't get why base64 defeat the purpose of OTP, it is just encoding nothing with encryption.
            – Aries_is_there
            2 days ago










          • Yes OTP is an highly safe encrypt way, it is quite difficult to crack all or any random ciphertexts. I suggest using bytes instead of just alphabets just for let it be more difficult to crack. and the key isn't something like here bank use, user can only input numbers (and you limit it to alphabets here), why not let it be more choice and be more tough for hackers
            – Aries_is_there
            2 days ago


















          • The base64 defeats the purpose of a one time pad. Also its not possible to get the string without the key, you can try to bruteforce it if you want to, you may or may not get the correct output try it with this one: zLFREvoTtPM. I see no proof that the original string can be bruteforced without the key itself.
            – 13aal
            2 days ago












          • It is meaningless to crack a random message with length just 11 and encrypted by OTP. Think of such a threat mode, the hacker know 2 mins ago you send your friend and an important encryped file, and you also send him the password encrypted using OTP, then hacker just need to crack messages around 2 mins ago and try to decrypt that file to verify it. And I don't get why base64 defeat the purpose of OTP, it is just encoding nothing with encryption.
            – Aries_is_there
            2 days ago










          • Yes OTP is an highly safe encrypt way, it is quite difficult to crack all or any random ciphertexts. I suggest using bytes instead of just alphabets just for let it be more difficult to crack. and the key isn't something like here bank use, user can only input numbers (and you limit it to alphabets here), why not let it be more choice and be more tough for hackers
            – Aries_is_there
            2 days ago
















          The base64 defeats the purpose of a one time pad. Also its not possible to get the string without the key, you can try to bruteforce it if you want to, you may or may not get the correct output try it with this one: zLFREvoTtPM. I see no proof that the original string can be bruteforced without the key itself.
          – 13aal
          2 days ago






          The base64 defeats the purpose of a one time pad. Also its not possible to get the string without the key, you can try to bruteforce it if you want to, you may or may not get the correct output try it with this one: zLFREvoTtPM. I see no proof that the original string can be bruteforced without the key itself.
          – 13aal
          2 days ago














          It is meaningless to crack a random message with length just 11 and encrypted by OTP. Think of such a threat mode, the hacker know 2 mins ago you send your friend and an important encryped file, and you also send him the password encrypted using OTP, then hacker just need to crack messages around 2 mins ago and try to decrypt that file to verify it. And I don't get why base64 defeat the purpose of OTP, it is just encoding nothing with encryption.
          – Aries_is_there
          2 days ago




          It is meaningless to crack a random message with length just 11 and encrypted by OTP. Think of such a threat mode, the hacker know 2 mins ago you send your friend and an important encryped file, and you also send him the password encrypted using OTP, then hacker just need to crack messages around 2 mins ago and try to decrypt that file to verify it. And I don't get why base64 defeat the purpose of OTP, it is just encoding nothing with encryption.
          – Aries_is_there
          2 days ago












          Yes OTP is an highly safe encrypt way, it is quite difficult to crack all or any random ciphertexts. I suggest using bytes instead of just alphabets just for let it be more difficult to crack. and the key isn't something like here bank use, user can only input numbers (and you limit it to alphabets here), why not let it be more choice and be more tough for hackers
          – Aries_is_there
          2 days ago




          Yes OTP is an highly safe encrypt way, it is quite difficult to crack all or any random ciphertexts. I suggest using bytes instead of just alphabets just for let it be more difficult to crack. and the key isn't something like here bank use, user can only input numbers (and you limit it to alphabets here), why not let it be more choice and be more tough for hackers
          – Aries_is_there
          2 days ago


















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207515%2fsimple-one-time-pad-cipher%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Morgemoulin

          Scott Moir

          Souastre