Header And Logo

PostgreSQL
| The world's most advanced open source database.

crypt-gensalt.c

Go to the documentation of this file.
00001 /*
00002  * Written by Solar Designer and placed in the public domain.
00003  * See crypt_blowfish.c for more information.
00004  *
00005  * contrib/pgcrypto/crypt-gensalt.c
00006  *
00007  * This file contains salt generation functions for the traditional and
00008  * other common crypt(3) algorithms, except for bcrypt which is defined
00009  * entirely in crypt_blowfish.c.
00010  *
00011  * Put bcrypt generator also here as crypt-blowfish.c
00012  * may not be compiled always.        -- marko
00013  */
00014 
00015 #include "postgres.h"
00016 
00017 #include "px-crypt.h"
00018 
00019 typedef unsigned int BF_word;
00020 
00021 static unsigned char _crypt_itoa64[64 + 1] =
00022 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00023 
00024 char *
00025 _crypt_gensalt_traditional_rn(unsigned long count,
00026                   const char *input, int size, char *output, int output_size)
00027 {
00028     if (size < 2 || output_size < 2 + 1 || (count && count != 25))
00029     {
00030         if (output_size > 0)
00031             output[0] = '\0';
00032         return NULL;
00033     }
00034 
00035     output[0] = _crypt_itoa64[(unsigned int) input[0] & 0x3f];
00036     output[1] = _crypt_itoa64[(unsigned int) input[1] & 0x3f];
00037     output[2] = '\0';
00038 
00039     return output;
00040 }
00041 
00042 char *
00043 _crypt_gensalt_extended_rn(unsigned long count,
00044                   const char *input, int size, char *output, int output_size)
00045 {
00046     unsigned long value;
00047 
00048 /* Even iteration counts make it easier to detect weak DES keys from a look
00049  * at the hash, so they should be avoided */
00050     if (size < 3 || output_size < 1 + 4 + 4 + 1 ||
00051         (count && (count > 0xffffff || !(count & 1))))
00052     {
00053         if (output_size > 0)
00054             output[0] = '\0';
00055         return NULL;
00056     }
00057 
00058     if (!count)
00059         count = 725;
00060 
00061     output[0] = '_';
00062     output[1] = _crypt_itoa64[count & 0x3f];
00063     output[2] = _crypt_itoa64[(count >> 6) & 0x3f];
00064     output[3] = _crypt_itoa64[(count >> 12) & 0x3f];
00065     output[4] = _crypt_itoa64[(count >> 18) & 0x3f];
00066     value = (unsigned long) (unsigned char) input[0] |
00067         ((unsigned long) (unsigned char) input[1] << 8) |
00068         ((unsigned long) (unsigned char) input[2] << 16);
00069     output[5] = _crypt_itoa64[value & 0x3f];
00070     output[6] = _crypt_itoa64[(value >> 6) & 0x3f];
00071     output[7] = _crypt_itoa64[(value >> 12) & 0x3f];
00072     output[8] = _crypt_itoa64[(value >> 18) & 0x3f];
00073     output[9] = '\0';
00074 
00075     return output;
00076 }
00077 
00078 char *
00079 _crypt_gensalt_md5_rn(unsigned long count,
00080                   const char *input, int size, char *output, int output_size)
00081 {
00082     unsigned long value;
00083 
00084     if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000))
00085     {
00086         if (output_size > 0)
00087             output[0] = '\0';
00088         return NULL;
00089     }
00090 
00091     output[0] = '$';
00092     output[1] = '1';
00093     output[2] = '$';
00094     value = (unsigned long) (unsigned char) input[0] |
00095         ((unsigned long) (unsigned char) input[1] << 8) |
00096         ((unsigned long) (unsigned char) input[2] << 16);
00097     output[3] = _crypt_itoa64[value & 0x3f];
00098     output[4] = _crypt_itoa64[(value >> 6) & 0x3f];
00099     output[5] = _crypt_itoa64[(value >> 12) & 0x3f];
00100     output[6] = _crypt_itoa64[(value >> 18) & 0x3f];
00101     output[7] = '\0';
00102 
00103     if (size >= 6 && output_size >= 3 + 4 + 4 + 1)
00104     {
00105         value = (unsigned long) (unsigned char) input[3] |
00106             ((unsigned long) (unsigned char) input[4] << 8) |
00107             ((unsigned long) (unsigned char) input[5] << 16);
00108         output[7] = _crypt_itoa64[value & 0x3f];
00109         output[8] = _crypt_itoa64[(value >> 6) & 0x3f];
00110         output[9] = _crypt_itoa64[(value >> 12) & 0x3f];
00111         output[10] = _crypt_itoa64[(value >> 18) & 0x3f];
00112         output[11] = '\0';
00113     }
00114 
00115     return output;
00116 }
00117 
00118 
00119 
00120 static unsigned char BF_itoa64[64 + 1] =
00121 "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
00122 
00123 static void
00124 BF_encode(char *dst, const BF_word *src, int size)
00125 {
00126     const unsigned char *sptr = (const unsigned char *) src;
00127     const unsigned char *end = sptr + size;
00128     unsigned char *dptr = (unsigned char *) dst;
00129     unsigned int c1,
00130                 c2;
00131 
00132     do
00133     {
00134         c1 = *sptr++;
00135         *dptr++ = BF_itoa64[c1 >> 2];
00136         c1 = (c1 & 0x03) << 4;
00137         if (sptr >= end)
00138         {
00139             *dptr++ = BF_itoa64[c1];
00140             break;
00141         }
00142 
00143         c2 = *sptr++;
00144         c1 |= c2 >> 4;
00145         *dptr++ = BF_itoa64[c1];
00146         c1 = (c2 & 0x0f) << 2;
00147         if (sptr >= end)
00148         {
00149             *dptr++ = BF_itoa64[c1];
00150             break;
00151         }
00152 
00153         c2 = *sptr++;
00154         c1 |= c2 >> 6;
00155         *dptr++ = BF_itoa64[c1];
00156         *dptr++ = BF_itoa64[c2 & 0x3f];
00157     } while (sptr < end);
00158 }
00159 
00160 char *
00161 _crypt_gensalt_blowfish_rn(unsigned long count,
00162                   const char *input, int size, char *output, int output_size)
00163 {
00164     if (size < 16 || output_size < 7 + 22 + 1 ||
00165         (count && (count < 4 || count > 31)))
00166     {
00167         if (output_size > 0)
00168             output[0] = '\0';
00169         return NULL;
00170     }
00171 
00172     if (!count)
00173         count = 5;
00174 
00175     output[0] = '$';
00176     output[1] = '2';
00177     output[2] = 'a';
00178     output[3] = '$';
00179     output[4] = '0' + count / 10;
00180     output[5] = '0' + count % 10;
00181     output[6] = '$';
00182 
00183     BF_encode(&output[7], (const BF_word *) input, 16);
00184     output[7 + 22] = '\0';
00185 
00186     return output;
00187 }