zoukankan      html  css  js  c++  java
  • 单机环境下基于口令的身份认证

    背景知识

    (1)口令字段信息的处理方法

    ① 接收用户提供的口令Dpw ;

    ② 生成一个盐值:Dsalt=Arandom( ) ;

    ③ 生成口令信息:s=Agen(Dsalt,Dpw) ;

    ④ 把口令信息s 和Dsalt 存入数据库的口令字段中。

    (2)口令字段信息的生成算法

    ① 给口令Dpw 撒盐:Dpw=Asalt(Dsalt,Dpw) ;

    ② 用撒盐结果做密钥:K=Dpw ;

    ③ 用一个64 位的全0 的二进制位串构造一个数据块Dp ;

    ④ 设循环次数初值:i=0 ;

    ⑤ 对数据块加密:Dc=Acrypt(K,Dp) ;

    ⑥ Dp=Dc, i=i+1 ;

    ⑦ 如果i<25 ,则回到⑤;

    ⑧ 把数据块变换成字符串:s=Atrans(Dc) ;

    ⑨ 返回s 。

    (3)给口令撒盐的算法

    ① 把盐值附加到口令上:Dtmp=Dpw||Dsalt ;

    ② 生成哈希值:Dhash=Ahash(Dtmp) ;

    ③ 以Dhash 作为返回结果。

    (4)身份认证算法

    ① 接收用户提供的账户名Dname 和口令Dpw ;

    ② 在账户信息数据库中检查Dname 的合法性,如果合法,则找出其对

    应的s 和Dsalt ;

    ③ 生成临时口令信息:sr=Agen(Dsalt,Dpw) ;

    ④ 如果sr=s ,则认证成功,否则,认证失败。

    具体操作过程

    编写代码pwprocessing.py

    import random
    import string
    #给口令加盐
    def addsalt(salt, pw):
        print("Adding salt...")
        pw = pw + salt
        print("Salt added.")
        return hash(pw)
    #加密的实现    
    def ecrypt(dp, key, i):
        print("Ecrypting data using your password...(round " + str(i+1) + ")")
        for i in range(0, len(dp)):
            index = i % len(key)
            if(key[index] == '-'):
                dp[i] = str(int(dp[i]) % 10)
            else:
                dp[i] = str((int(dp[i]) + int(key[index])) % 10)
        return dp
    #口令字段信息的生成算法
    def generate(salt, pw):
        print("Generating data ecrypted by your password...")
        #给口令Dpw 撒盐,用撒盐结果做密钥
        saltedpw = str(addsalt(salt, pw))
        dp = []
        #用一个64 位的全0 的二进制位串构造一个数据块
        for i in range(0, 64):
            dp.append('0')
        #对数据块加密
        for i in range(0, 25):
            dp = ecrypt(dp, saltedpw, i)
        print("Data ecrypted by your password generated.")
        return dp
    
    #创建用户
    def createuser(database):
        print("Creating user...")
        print("Input 'q' as username if you want to quit.")
        while(1):
            name = input("username: ")
            if name == 'q':
                break
            pw = input("password: ")
            salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
            s = generate(salt, pw)
            dic = {}
            dic['name'] = name
            dic['salt'] = salt
            dic['pw'] = s
            database.append(dic)
            print("User " + name + " is created.")
    #直接通过字典匹配用户,检查此用户是否存在
    def has_user(database, name):
        for dic in database:
            if dic['name'] == name:
                return 1
        return 0
    #得到用户的具体信息
    def get_info(database, name):
        for dic in database:
            if dic['name'] == name:
                salt = dic['salt']
                s = dic['pw']
                return salt, s
    #身份认证算法
    def authenticate(database):
        print("Authenticating user...")
        print("Input 'q' as username if you want to quit.")
        while(1):
            #接收用户提供的账户名Dname ;
            name = input("username: ")
            if name == 'q':
                break
            flag = has_user(database, name)
            if flag == 0:
                print("Sorry, user " + name + " does not exist.")
                continue
            #接受用户提供的口令
            pw = input("password: ")
            #在账户信息数据库中检查Dname 的合法性,如果合法,则找出其对
            #应的s 和Dsalt
            salt, s = get_info(database, name)
            #生成临时口令信息
            sr = generate(salt, pw)
            print("Comparing ecrypted data...")
            if(s == sr):
                print("User " + name + " authenticated.")
            else:
                print("Sorry, the password is wrong.")
    database = []
    createuser(database)
    authenticate(database)

    创建用户

    ① 创建第一个用户”csz”,密码为”csz”

     

    ② 创建第二个用户”cy”,密码为”cy”

     

    验证用户

    ① 输入不存在的用户名”feng”

     

    ② 输入用户名”csz”和正确的密码”csz”

     

    ③ 输入用户名”cy”和错误的密码”521”

     

    ③ 输入用户名”cy”和正确的密码”cy”

     

    c++ 实现如下,但思路不同,注意 c++编译时把"-std=c++11"修改为"-std=gnu++0x"

    otp.cpp

    #include "md5.h"
    #include<iostream>
    #include<string>
    #include<stdlib.h>
    #include<time.h>
    #include<fstream>
    using namespace std;
    
    struct inf  //系统用户存储信息结构
    {
        char uid[50]; //用户名
        int r;  //挑战值
        char answer[50]; //应答值
        char password[50]; //密码
    };
    
    inf infor[300];
    int n=0;
    
    void init()
    {
        char uid[50],answer[50],password[50];
        int r;
        fstream file; 
        file.open("lib.txt",ios::in);
        if(!file);
        else
        {
            while(file>>uid>>r>>answer>>password)
            {
                strcpy(infor[n].uid,uid);
                infor[n].r=r;
                strcpy(infor[n].answer,answer);
                strcpy(infor[n].password,password);
                n++;
            }
        }
        file.close();
    }
    
    void reg()
    {
        char uid[50],password1[50],password2[50],ans[100]={0},answer[50];
        int r,i;
        while(1)
        {
            cout<<"请输入用户名: ";
            cin>>uid;
            for(i=0;i<n;i++)
                if(strcmp(infor[i].uid,uid)==0)
                {
                    cout<<endl<<"该用户名已存在!"<<endl<<endl;
                    break;
                }
            if(i==n) break;
        }
        while(1)
        {
            cout<<"请输入密码: ";
            cin>>password1;
            cout<<"请再次输入密码: ";
            cin>>password2;
            if(strcmp(password1,password2)==0)
                break;
            else
            {
                cout<<endl<<"两次密码不一致!"<<endl<<endl;
            }
        }
        srand(time(0));
        r=rand();
        infor[n].r=r;
        i=0;
        while(r!=0)
        {
            ans[i]=r%10+'0';
            r/=10;
            i++;
        }
        strcat(ans,password1);
        strcpy(answer,MD5String(ans));    
    
        strcpy(infor[n].uid,uid);
        strcpy(infor[n].answer,answer);
        strcpy(infor[n].password,password1);
        n++;
    
        cout<<endl<<"用户注册成功!"<<endl<<endl;
        system("pause");
        system("cls");
    }
    
    void check()
    {
        char uid[50],answer[50],ans[100]={0};
        int r,i,j;
        char ch;
        cout<<"请输入用户名: ";
        cin>>uid;
        for(i=0;i<n;i++)
        {
            if(strcmp(infor[i].uid,uid)==0)
            {
                cout<<"挑战值为: "<<infor[i].r<<endl;                        
                cout<<"是否返回进行应答值计算(y/n): ";
                cin>>ch;
                if(ch=='y') cout<<endl;
                else if(ch=='n')
                {                    
                    cout<<"请输入应答值: ";
                    cin>>answer;
                    if(strcmp(answer,infor[i].answer)==0)
                    {
                        cout<<endl<<"认证通过!"<<endl<<endl;
                        srand(time(0));
                        r=rand();
                        infor[i].r=r;
                        j=0;
                        while(r!=0)
                        {
                            ans[j]=r%10+'0';
                            r/=10;
                            j++;
                        }
                        strcat(ans,infor[i].password);                
                        strcpy(infor[i].answer,MD5String(ans));
                    }
                    else
                        cout<<endl<<"认证失败!"<<endl<<endl;
                }
                else cout<<endl<<"输入错误!"<<endl<<endl;
                break;
            }
        }
        if(i==n)
            cout<<endl<<"该用户名不存在!"<<endl<<endl;
        system("pause");
        system("cls");    
    }
    
    void compute()
    {
    
        char password[50],answer[50],ans[100]={0};
        int r,i;
    
        cout<<"请输入挑战值: ";
        cin>>r;
        cout<<"请输入密码: ";
        cin>>password;
    
        i=0;
        while(r!=0)
        {
            ans[i]=r%10+'0';
            r/=10;
            i++;
        }
        strcat(ans,password);
        strcpy(answer,MD5String(ans));
        cout<<endl<<"应答值为: "<<answer<<endl<<endl;
    
        system("pause");
        system("cls");
    
    }
    
    int main()
    {
        char ch; 
        int i;
        init();
        while(1)
        {
            cout<<endl;
            cout<<"                             1.用户注册"<<endl<<endl
                <<"                             2.身份认证"<<endl<<endl
                <<"                             3.口令计算"<<endl<<endl
                <<"                             0.退出"<<endl<<endl;
            cout<<"请选择: ";
            cin>>ch;
            cout<<endl;
            if(ch=='0') break;
            switch(ch)
            {
            case '1': reg(); break; //用户注册
            case '2': check(); break; //身份认证
            case '3': compute(); break; //口令计算
            default: cout<<"输入错误!"<<endl;
                     system("pause");
                     system("cls");
            }
        }
        fstream f;
        f.open("lib.txt",ios::out);
        for(i=0;i<n;i++)
            f<<infor[i].uid<<'	'<<infor[i].r<<'	'<<infor[i].answer<<'	'<<infor[i].password<<endl;
    
        return 1;
    }

    md5.h

    #ifndef HEADER_FILE
    #define HEADER_FILE
    
    #include <assert.h>
    #include <stdio.h>
    #include <string.h>
    
    
    typedef unsigned       int uint4;
    typedef unsigned short int uint2;
    typedef unsigned      char uchar;
    uint4    m_State[4];
    uint4    m_Count[2];
    uchar    m_Buffer[64];
    uchar    m_Digest[16];
    uchar    m_Finalized;
    char* PrintMD5(uchar md5Digest[16]);
    char* MD5String(char* szString);
    char* MD5File(char* szFilename);
    
    void Init();
    void Update(uchar* chInput, uint4 nInputLen);
    void Finalize();
    uchar* Digest() { return m_Digest; }
    
    void Transform(uchar* block);
    void Encode(uchar* dest, uint4* src, uint4 nLength);
    void Decode(uint4* dest, uchar* src, uint4 nLength);
    
    inline uint4 rotate_left(uint4 x, uint4 n)
    { return ((x << n) | (x >> (32-n))); }
    
    inline uint4 F(uint4 x, uint4 y, uint4 z)
    { return ((x & y) | (~x & z)); }
    
    inline uint4 G(uint4 x, uint4 y, uint4 z)
    { return ((x & z) | (y & ~z)); }
    
    inline uint4 H(uint4 x, uint4 y, uint4 z)
    { return (x ^ y ^ z); }
    
    inline uint4 I(uint4 x, uint4 y, uint4 z)
    { return (y ^ (x | ~z)); }
    
    inline void FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
    { a += F(b, c, d) + x + ac; a = rotate_left(a, s); a += b; }
    
    inline void GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
    { a += G(b, c, d) + x + ac; a = rotate_left(a, s); a += b; }
    
    inline void HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
    { a += H(b, c, d) + x + ac; a = rotate_left(a, s); a += b; }
    
    inline void II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
    { a += I(b, c, d) + x + ac; a = rotate_left(a, s); a += b; }
    
    
    static unsigned char PADDING[64] =
    {
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };
    
    #define S11 7
    #define S12 12
    #define S13 17
    #define S14 22
    #define S21 5
    #define S22 9
    #define S23 14
    #define S24 20
    #define S31 4
    #define S32 11
    #define S33 16
    #define S34 23
    #define S41 6
    #define S42 10
    #define S43 15
    #define S44 21
    
    char* PrintMD5(uchar md5Digest[16])
    {
        char chBuffer[256];
        char chEach[10];
        int nCount;
    
        memset(chBuffer,0,256);
        memset(chEach, 0, 10);
    
        for (nCount = 0; nCount < 16; nCount++)
        {
            sprintf(chEach, "%02x", md5Digest[nCount]);
            strncat(chBuffer, chEach, sizeof(chEach));
        }
    
        return strdup(chBuffer);
    }
    
    char* MD5String(char* szString)
    {
        Init();
        int nLen = strlen(szString);
        Update((unsigned char*)szString, (unsigned int)nLen);
        Finalize();
    
        return PrintMD5(Digest());
    
    }
    char* MD5File(char* szFilename)
    {
        FILE* file;
        int nLen;
        unsigned char chBuffer[1024];
    
        try
        {
            memset(chBuffer, 0, 1024);
    
            if ((file = fopen (szFilename, "rb")) != NULL)
            {
                while (nLen = fread (chBuffer, 1, 1024, file))
                    Update(chBuffer, nLen);
    
                Finalize();
    
                fclose (file);
    
                return PrintMD5(Digest());
            }
        }
        catch(...)
        {
    
        }
    
        return NULL; // failed
    }
    
    void Init()
    {
        memset(m_Count, 0, 2 * sizeof(uint4));
    
        m_State[0] = 0x67452301;
        m_State[1] = 0xefcdab89;
        m_State[2] = 0x98badcfe;
        m_State[3] = 0x10325476;
    }
    
    void Update(uchar* chInput, uint4 nInputLen)
    {
        uint4 i, index, partLen;
    
        // Compute number of bytes mod 64
        index = (unsigned int)((m_Count[0] >> 3) & 0x3F);
    
        // Update number of bits
        if ((m_Count[0] += (nInputLen << 3)) < (nInputLen << 3))
            m_Count[1]++;
    
        m_Count[1] += (nInputLen >> 29);
    
        partLen = 64 - index;
    
        // Transform as many times as possible.
        if (nInputLen >= partLen)
        {
            memcpy( &m_Buffer[index], chInput, partLen );
            Transform(m_Buffer);
    
            for (i = partLen; i + 63 < nInputLen; i += 64)
                Transform(&chInput[i]);
    
            index = 0;
        }
        else
            i = 0;
    
        // Buffer remaining input
        memcpy( &m_Buffer[index], &chInput[i], nInputLen-i );
    }
    
    void Finalize()
    {
        uchar bits[8];
        uint4 index, padLen;
    
        // Save number of bits
        Encode (bits, m_Count, 8);
    
        // Pad out to 56 mod 64
        index = (unsigned int)((m_Count[0] >> 3) & 0x3f);
        padLen = (index < 56) ? (56 - index) : (120 - index);
        Update(PADDING, padLen);
    
        // Append length (before padding)
        Update (bits, 8);
    
        // Store state in digest
        Encode (m_Digest, m_State, 16);
    
        memset(m_Count, 0, 2 * sizeof(uint4));
        memset(m_State, 0, 4 * sizeof(uint4));
        memset(m_Buffer,0, 64 * sizeof(uchar));
    }
    
    void Transform (uchar* block)
    {
        uint4 a = m_State[0], b = m_State[1], c = m_State[2], d = m_State[3], x[16];
    
        Decode (x, block, 64);
    
        // Round 1
        FF (a, b, c, d, x[ 0], S11, 0xd76aa478);
        FF (d, a, b, c, x[ 1], S12, 0xe8c7b756);
        FF (c, d, a, b, x[ 2], S13, 0x242070db);
        FF (b, c, d, a, x[ 3], S14, 0xc1bdceee);
        FF (a, b, c, d, x[ 4], S11, 0xf57c0faf);
        FF (d, a, b, c, x[ 5], S12, 0x4787c62a);
        FF (c, d, a, b, x[ 6], S13, 0xa8304613);
        FF (b, c, d, a, x[ 7], S14, 0xfd469501);
        FF (a, b, c, d, x[ 8], S11, 0x698098d8);
        FF (d, a, b, c, x[ 9], S12, 0x8b44f7af);
        FF (c, d, a, b, x[10], S13, 0xffff5bb1);
        FF (b, c, d, a, x[11], S14, 0x895cd7be);
        FF (a, b, c, d, x[12], S11, 0x6b901122);
        FF (d, a, b, c, x[13], S12, 0xfd987193);
        FF (c, d, a, b, x[14], S13, 0xa679438e);
        FF (b, c, d, a, x[15], S14, 0x49b40821);
    
        // Round 2
        GG (a, b, c, d, x[ 1], S21, 0xf61e2562);
        GG (d, a, b, c, x[ 6], S22, 0xc040b340);
        GG (c, d, a, b, x[11], S23, 0x265e5a51);
        GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
        GG (a, b, c, d, x[ 5], S21, 0xd62f105d);
        GG (d, a, b, c, x[10], S22, 0x2441453);
        GG (c, d, a, b, x[15], S23, 0xd8a1e681);
        GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
        GG (a, b, c, d, x[ 9], S21, 0x21e1cde6);
        GG (d, a, b, c, x[14], S22, 0xc33707d6);
        GG (c, d, a, b, x[ 3], S23, 0xf4d50d87);
        GG (b, c, d, a, x[ 8], S24, 0x455a14ed);
        GG (a, b, c, d, x[13], S21, 0xa9e3e905);
        GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8);
        GG (c, d, a, b, x[ 7], S23, 0x676f02d9);
        GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);
    
        // Round 3
        HH (a, b, c, d, x[ 5], S31, 0xfffa3942);
        HH (d, a, b, c, x[ 8], S32, 0x8771f681);
        HH (c, d, a, b, x[11], S33, 0x6d9d6122);
        HH (b, c, d, a, x[14], S34, 0xfde5380c);
        HH (a, b, c, d, x[ 1], S31, 0xa4beea44);
        HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9);
        HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60);
        HH (b, c, d, a, x[10], S34, 0xbebfbc70);
        HH (a, b, c, d, x[13], S31, 0x289b7ec6);
        HH (d, a, b, c, x[ 0], S32, 0xeaa127fa);
        HH (c, d, a, b, x[ 3], S33, 0xd4ef3085);
        HH (b, c, d, a, x[ 6], S34, 0x4881d05);
        HH (a, b, c, d, x[ 9], S31, 0xd9d4d039);
        HH (d, a, b, c, x[12], S32, 0xe6db99e5);
        HH (c, d, a, b, x[15], S33, 0x1fa27cf8);
        HH (b, c, d, a, x[ 2], S34, 0xc4ac5665);
    
        // Round 4
        II (a, b, c, d, x[ 0], S41, 0xf4292244);
        II (d, a, b, c, x[ 7], S42, 0x432aff97);
        II (c, d, a, b, x[14], S43, 0xab9423a7);
        II (b, c, d, a, x[ 5], S44, 0xfc93a039);
        II (a, b, c, d, x[12], S41, 0x655b59c3);
        II (d, a, b, c, x[ 3], S42, 0x8f0ccc92);
        II (c, d, a, b, x[10], S43, 0xffeff47d);
        II (b, c, d, a, x[ 1], S44, 0x85845dd1);
        II (a, b, c, d, x[ 8], S41, 0x6fa87e4f);
        II (d, a, b, c, x[15], S42, 0xfe2ce6e0);
        II (c, d, a, b, x[ 6], S43, 0xa3014314);
        II (b, c, d, a, x[13], S44, 0x4e0811a1);
        II (a, b, c, d, x[ 4], S41, 0xf7537e82);
        II (d, a, b, c, x[11], S42, 0xbd3af235);
        II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
        II (b, c, d, a, x[ 9], S44, 0xeb86d391);
    
        m_State[0] += a;
        m_State[1] += b;
        m_State[2] += c;
        m_State[3] += d;
    
        memset(x, 0, sizeof(x));
    }
    
    void Encode(uchar* dest, uint4* src, uint4 nLength)
    {
        uint4 i, j;
    
        //assert(nLength % 4 == 0);
    
        for (i = 0, j = 0; j < nLength; i++, j += 4)
        {
            dest[j] = (uchar)(src[i] & 0xff);
            dest[j+1] = (uchar)((src[i] >> 8) & 0xff);
            dest[j+2] = (uchar)((src[i] >> 16) & 0xff);
            dest[j+3] = (uchar)((src[i] >> 24) & 0xff);
        }
    }
    
    void Decode(uint4* dest, uchar* src, uint4 nLength)
    {
        uint4 i, j;
    
        //assert(nLength % 4 == 0);
    
        for (i = 0, j = 0; j < nLength; i++, j += 4)
        {
            dest[i] = ((uint4)src[j]) | (((uint4)src[j+1])<<8) |
                (((uint4)src[j+2])<<16) | (((uint4)src[j+3])<<24);
        }
    }
    
    #endif;

    编译运行结果如下

  • 相关阅读:
    事务 ~ 锁
    JDBC
    C# ~ 由 IDisposable 到 GC
    C# ~ 泛型委托
    函数式编程
    反射
    测试初识
    C# ~ 从 委托事件 到 观察者模式
    C# ~ 从 IEnumerable / IEnumerator 到 IEnumerable<T> / IEnumerator<T> 到 yield
    Java初识
  • 原文地址:https://www.cnblogs.com/caishunzhe/p/12819385.html
Copyright © 2011-2022 走看看