单机环境下基于口令的身份认证

背景知识

(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;

编译运行结果如下

原文地址:https://www.cnblogs.com/caishunzhe/p/12819385.html