No announcement yet.


  • Filter
  • Time
  • Show
Clear All
new posts

  • PassKey

    Passwords are convenient. They may be so easy to remember that we don't need to write them down. They are also easy to crack as well. Passphrases, in general, are better because they are likely to be longer and may include more than just alpha-numeric characters. A whole lot of either and we may wish we had a better memory.

    From a security view, better still is a password with random characters. Chances are though we are not going to remember them.

    NIST have a formula for random characters: Entropy = log²(n^k) where log² denotes log to base 2, n is the number of available characters and k is the password length. The greater the entropy the more secure the password.

    The formula clearly shows that the entropy increases as both n and k increase. This confirms that, in general, passphrases are better than passwords.

    With a character set of lower/upper case and 0 to 9 we have, for 16 characters chosen at random, an entropy of 95.3 Alternatively, with a standard 94 character keyboard and 16 characters chosen at random we have an entropy of 104.9.

    For a character set comprising the values 0 to 255, 16 characters chosen at random gives an entropy of 128.

    In the latter case, we don't need the formula. Here we have the maximum possible entropy per byte, ie 8 bits, so the entropy is simpy 8 x 16 = 128.

    A random binary string, or binary key, then gives the maximum entropy for a given password length.

    Not surprisingly, many encryption applications have a key input as a hexadecimal string.

    Few of us, if any, will be able to remember binary strings even when represented as hexadecimal. We are bound then to save them somewhere.

    We could have the most sophisticated method to ensure that our keys are safe. By 'We' I mean the sender of the encrypted file. The object may be defeated if the recipient has the key stuck on the front of their monitor. I've never seen anyone mention this. Perhaps it is supposed to go without saying. Problem is that the sender cannot be 100% sure that this is the case.

    Another method of employing a binary key is via a key file. Here, a file is hashed by a secure hash algorithm and the resulting hash value is used as the key. This method is used by TrueCrypt and KeePass to mention just two applications. This author's HashFile also employs this method. We have then a resulting binary key which does not have to be saved - we only have to remember the key file used. An image from \My Documents\My Pictures is handy as browsing with an open file dialog shows the thumbnails.

    I haven't seen a criticism of this method but there may be one. My C: drive has just over 100,000 files. 100,000 may be represented as 2^16.6. This is tiny when compared with a 128 bit key giving 2^128 combinations. Of course, we are not talking about 2^16.6 keys but 2^16.6 hashes and the bigger the key file the longer to calculate the hash value.

    However, it is a point even if the key files were on other media.

    Suppose, instead of one key file we chose two. If the order is important then we must consider permutations. The formula for permutations is n!/(n - k)! where ! is factorial, n is the number of objects and k is the permutation size.

    For k = 2 the formula reduces to n!/(n-2)! = n x (n-1). If we allow the same file to be chosen twice then this adds a further n resulting in a total of n^2.

    So, by choosing two files we don't double the security, we square it. Our 100,000 files now gives 10 billion pairs and, therefore, 20 billion hashes.

    What have I opted for then? None. It is left up to the user of PassKey.

    Passkey will accept the following, ordered by security level.

    One key file.
    Two key files.
    A binary key.
    A binary key plus one key file.
    A binary key plus two key files.

    The level is debatable since it could be argued that a saved binary key may not be as secure as remembering two key files or even one.

    If a binary key is used it will be hashed. This ensures that short or long keys, short or long relative to the chosen bit level required of the output key, are equal to the chosen bit level of the output key.

    To keep things simple the hash algorithm used is SHA512 and clipped according to the bit level of the output key. Thanks to Greg Turgeon for his SHA512 implementation.

    The bit level of the output key may be 128, 160, 192, 256 or 512. Of course, we can have others simply by further clipping by hand.

    A cancelled key file browse will empty that key file, if it wasn't already empty.

    Here is PassKey on opening:

    There are no defaults, no drag and drop for the Input key, no obscuring and no indication of the key files chosen.

    If you have any comments then let them rip.

    PassKey is attached - zipped as a folder. No help file - that is why I've rambled above.
    Attached Files
    Last edited by David Roberts; 23 Apr 2009, 09:07 AM.

  • #2
    A Drag & Drop feature has been added to the Input Key text box.

    If the contents of the file are greater than 128 bytes or not an even number of bytes or not wholly hexadecimal then the drop will fail. If successful then the text box will be obscured.

    Security-wise this is better than typing or a 'Copy and Paste'.

    At the moment this is allowed only once per PassKey session. No particular reason - I haven't fathomed a way to avoid it yet.

    V1.01 uploaded in 1st post.
    Last edited by David Roberts; 19 Apr 2009, 01:02 AM.


    • #3
      > At the moment this is allowed only once per PassKey session. No particular reason - I haven't fathomed a way to avoid it yet.

      MSDN: When an edit control has the ES_READONLY style, the user cannot change the text within the edit control.

      Maybe not via the keyboard but a 'Drag & Drop' still works. So, no additional code required.

      The Key files checkbox is now a 3State. Selections, if any, are grayed out if the Key file is empty.

      Slight tidying up of GUI.

      V1.02 uploaded in 1st post.

      PS I keep forgetting to mention that the Topmost execution may be altered via the System menu or via right clicking on the title bar. With a minimize button there probably is no need to remove the Topmost feature but I always include this option should anyone need it.

      PPS I'm sure I don't need to mention this but it is something that we may forget. With a shortcut's 'Start in:' text box of the properties sheet set to \My Documents\My Pictures then the open file dialog will start in that directory no matter where we have put PassKey.
      Last edited by David Roberts; 19 Apr 2009, 09:10 PM.


      • #4
        I've just received a great idea from Eddy Van Esch.

        To make finding the key by brute force more costly, I once saw a NIST document (can't remember which one it was though..) that suggested to use a sequence of 'n' hash calculations, like this:
        h1 = SHA_xx(key || keyfile)
        h2 = SHA_xx(h1)
        hn = SHA_xx(h(n-1))
        where hn is the actual output key and n any number you like.
        So, I have done just that. The additional overhead per hash is negligible as hi is only 64 bytes.

        There is one aspect of this subject that is important and that is to be clear what is been done. We need to be open to everyone even Mr Villain & Co.

        Anyway, the value of n chosen. It is ... erm. Oh, dear. I should have written it down. Errrr .... Sorry? Oh, milk, no sugar. Thank you. Pardon? Yeah, it has turned out nice.

        V1.03 uploaded in 1st post.
        Last edited by David Roberts; 20 Apr 2009, 05:40 AM.


        • #5
          The value of n in post #4 can be got very easily.

          An attacker could feed PassKey an input and note the output key. All that is required is to write a similar application and count the iterations until a match is found. Job done.

          The method's principal use is in deriving a key from a password. Iterating the algorithm used in the intermediary stage puts distance between the password and the derived key encumbering an attack on the password. Applying iterations on a derived key is a waste of time.

          The Input key may be regarded as a derived key. The Key files, on the other hand, may be regarded as passwords and a brute force attack would require access to whence they came. This is one of the strengths of using Key files besides not having to save a key.

          Generally, this consideration should only be relevant if a Key input is not employed. However, if a Key input's security has been compromised then its entropy vanishes. Since the latter may be true without our knowledge then this consideration should then be mandatory.

          If we could ensure that the Key files were no less than a certain size then we could dispense with the hash iteration method.

          On my system tests have shown that a couple of 5MB files take about 400ms to load and process.

          The method now employed will take any file less than 5MB and pad up to 5MB with random bytes using RND and a seed equal to the length of the file. So, given any file population PassKey will effectively not see any file less than 5MB.

          A couple of 1KB files took 890ms to load and process and a couple of files 1KB shy of 5MB took 408ms. These figures, of course, will depend upon the storage media employed and the CPU.

          Waiting less than a second for an Output key to be calculated should be bearable but an attacker faced with that would not be best pleased.

          I'm sure that if you do send encrypted files using classical algorithms then you will be aware that they are not proof of integrity - classical decryption is oblivious to alteration - accidental or intended. An encrypted file should be accompanied with its hash value. Better still would be a HMAC which would prove authenticity as well as integrity.

          HMACs require a password.

          Passwords are convenient. They may be so easy to remember that we don't need to write them down. They are also easy to crack as well ......

          V1.04 uploaded in 1st post.
          Last edited by David Roberts; 21 Apr 2009, 06:02 PM.


          • #6
            I sneezed and the above got posted twice.
            Last edited by David Roberts; 21 Apr 2009, 06:07 PM.


            • #7
              My logic is wrong in the last post with regard the hash iterations - I should say last but one.

              However, I shall stay with the file padding if a file is less than 5MB. If only an Input Key is employed then the file padding doesn't play a part. If a Key file is used then padding may be employed whether an Input Key exists or not. If two Key files are used then padding may be employed on both and, again, whether an Input Key exists or not.

              The hash iteration method applied itself to the whole shooting match.

              Now, where did my logic fail?

              If we look at Eddy's last equation in post #4 we have hn = SHA_xx(h(n-1))

              This could be written as hn = SHA_xx(SHA_xx(h(n-2))) = SHA_xx^2(h(n-2))
              This could be written as hn = SHA_xx^(n-1)(h(1))

              and finally we get hn = SHA_xx^n(key || keyfile)

              One brute force technique is called a dictionary attack. We simply try all the words in an exhaustive list.

              The exhaustive list in our context is the population of files that the Key file/s is/are taken from.

              A dictionary attack targets the password. In our context the Key files may be regarded as passwords, I got that right above , so the Key file/s is/are the target.

              To put some distance between the Key file/s and the derived key, hn, we simply choose a sufficiently large n.

              In Eddy's words "To make finding the key by brute force more costly"

              The file padding also introduces a cost but the cost is embedded in the data stream.

              With an Input Key and two Key files we have:-

              Iterate method: hn = SHA_xx^n(key || keyfile1 || keyfile2)
              Padding method: h = SHA_xx(key || keyfile1 || padding1 || keyfile2 || padding2)

              I get there in the end - glad that I don't have to wear a hair shirt until I do.

              There is nothing to upload this time.
              Last edited by David Roberts; 21 Apr 2009, 10:52 PM. Reason: I should say last but one


              • #8
                I've just thought of another benefit of the padding method. RND is proprietary.

                For small Key files a heck of a lot of data is being added. As Key files tend to 5MB the padding tends to zero but the combination is still 5MB of data.

                It hadn't occurred to me but the Key file/password analogy carries into padding/salt. In our case we have a variable size salt and it is public.

                Even if the attackers code used PB's RND it will still be looking at 5MB or more of data per hash - the basis upon which the padding was introduced.

                I had another look at the iterative method. The time taken with the first iterate depends upon the input data. Thereafter, we are repeatedly hashing 64 bytes. This means that the additional work is fixed which is a good thing since its influence will be stronger with smaller files. However, when compared with the padding approach it became clear that the size of n chosen was too small. If we increase it so that it is more effective we'll end up adding too much to larger files when they don't need it. 'n' then needs to be dynamic and inversely proportional to the key files size. It follows then that it we cannot have a dynamic 'n' if Key files are not used but we don't need a delaying tactic then since the dictionary associated with a binary string has a size equal to 2^(bit length) of the Input key. If the Input key is compromised then we are trouble but that is another reason for using Key files as well. For me, a dynamic 'n' would make the iterative approach a contender again.

                Salts are normally private/secret. If we used a secret padding then we could get away with less and use it in the traditional way by adding to every Key file. The padding is created on the fly so the 'salt' would be the seed for the random number generation. One approach would be to add a salt to the length of the file which is used now as the seed.

                The problem now is where do we put the salt and if that gets compromised we'd need a backup like the iterative method.

                On balance I think the public padding is the best of the bunch so far.


                • #9
                  One last tweak before I rap this up - famous last words.

                  I figured that if two Key files are used then padding to 5MB as required is a bit much. At first I thought a 5MB lower limit if one Key file used and 2½MB lower limit if two Key files are used. When I looked at the maths I found that we don't need to use padding if two Key files are used. It is difficult to comprehend the increased level of difficulty imposed on an attacker by using two Key files as opposed to one. An analogy is to compare SHA256 with MD5 implementing 256 bits and 128 bits respectively. SHA256 is effectively MD5^2; or 2^128 x MD5 or 10^38 x MD5. To me, MD5^2 doesn't say much. 2^128 x MD5 says more but I still don't sense the size. I do with 10^38 x MD5. Yeah? Actually, it is 10^38.5318 with more precision but we lose the poetry.

                  So, with one Key file all files greater than or equal to 5MB are hashed as is; smaller files are padded to 5MB with random numbers using PB's propriety generator with a seed equal to the Key file length.

                  For two Key files the files are hashed as is.

                  A friend contacted me and asked what was the best way to send the Output key. I told him that if an Input key is used then the recipient needs it as well. If one or more Key files are used then the recipient needs them on their machine as well. The Output key isn't sent anywhere. My head only needed the one stitch.

                  V1.05 uploaded in 1st post.
                  Last edited by David Roberts; 23 Apr 2009, 09:36 AM.