Linux C/C++实现随机密码生成器

当您使用用户名和密码对服务进行身份验证时,强密码非常重要。一个强密码必须至少有14个字符,并有大小写字母和字母等变体。大多数时候,长密码被认为比短密码安全得多,因为它很难获得。

下面我们将学习使用Linux命令行创建安全密码的多种方法。我们将研究使用Linux命令行创建更强、更安全的密码的多种不同方法。如果要使用命令行创建强密码,可以使用多种方法和实用程序。我们将讨论其中的许多方法,可以根据需要选择其中一种方法来创建密码。

使用urandom生成密码

我们用来生成密码的第一个命令已经用tr命令过滤了/dev/urandom输出。这将允许我们删除所有不需要的字符,然后帮助我们只打印前14个字符。

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 14;echo

上述命令的输出如下:

输出允许我们仅通过删除所有不需要的字符来打印前14个字符。


...
void gendigit(int size)
{ 
...

    f = fopen("/dev/urandom", "r");
    for (i=0; i<size; i++) 
    {
        fread(&randval, sizeof(randval), 1, f);
        pass[i] = list[randval % 10];
        printf("%c", pass[i]);
    }
...
}
int main(int argc, char *argv[]) 
{
...

    switch (argc) 
    {
        case 1: genalpha(length); break;
        case 2: 
                if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) 
                {
                    HELP
                } 
                
                length = atoi(argv[1]);

                if (length < 6 || length > 32) 
                {
                    printf("Error: Password size must be a number between 6 and 32\n\n");
                    HELP
                }
                genalpha(length); break;
        case 3:
                length = atoi(argv[2]);
                
                if(length < 6 || length > 32) 
                {
                    printf("Error: Password size must be a number between 6 and 32\n\n");
                    HELP
                }

                /* 检查正在传递的参数 */
                if (!strcmp(argv[1], "-s") || !strcmp(argv[1], "--symbol")) 
                {
                    gensymbol(length);
                } 
                else if (!strcmp(argv[1], "-a") || !strcmp(argv[1], "--alphanum")) 
                {
                    genalpha(length);
                } 
                else if (!strcmp(argv[1], "-d") || !strcmp(argv[1], "--digits")) 
                {
                    gendigit(length);
                } 
                else {
                    HELP
                }
                break;
        default: HELP 
    }
}
...

运行结果:

Linux C/C++实现随机密码生成器_第1张图片

使用SHA生成密码

我们将在这个方法中使用SHA,它被设计用来使用 SHA-256 算法(SHA-2 系列,摘要长度为 256 位)校验数据完整性。

date | sha256sum

...
void sha256(const char* str)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str, strlen(str));
    SHA256_Final(hash, &sha256);
    
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
        printf("%02x", (int)hash[i]);
    }
    printf("\n");
}

int main(int argc, char *argv[]) 
{
    sha256("asdfqwr12");
    return 0;
}

编译运行:

通过md5sum简单的方式生成密码

使用命令行可以很容易地生成密码。虽然它不是随机的,但如果我们使用整个密码,它仍然很有用。为此,最简单的命令如下:

date | md5sum

在这里插入图片描述

一种获取可用作密码的随机字符串的方法是计算 MD5 校验值!校验值看起来确实像是随机字符串组合在一起,我们可以用作密码。确保你的计算源是个变量,这样的话每次运行命令时生成的校验值都不一样。date 命令 总会生成不同的输出。




static void Transform (UINT4 *buf, UINT4 *in) {

	UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];

#define S11 7
#define S12 12
#define S13 17
#define S14 22
	FF ( a, b, c, d, in[ 0], S11, 3614090360UL);
	FF ( d, a, b, c, in[ 1], S12, 3905402710UL);
	FF ( c, d, a, b, in[ 2], S13,	606105819);
	FF ( b, c, d, a, in[ 3], S14, 3250441966UL);
	FF ( a, b, c, d, in[ 4], S11, 4118548399UL);
	FF ( d, a, b, c, in[ 5], S12, 1200080426);
	FF ( c, d, a, b, in[ 6], S13, 2821735955UL);
	FF ( b, c, d, a, in[ 7], S14, 4249261313UL);
	FF ( a, b, c, d, in[ 8], S11, 1770035416);
	FF ( d, a, b, c, in[ 9], S12, 2336552879UL);
	FF ( c, d, a, b, in[10], S13, 4294925233UL);
	FF ( b, c, d, a, in[11], S14, 2304563134UL);
	FF ( a, b, c, d, in[12], S11, 1804603682);
	FF ( d, a, b, c, in[13], S12, 4254626195UL);
	FF ( c, d, a, b, in[14], S13, 2792965006UL);
	FF ( b, c, d, a, in[15], S14, 1236535329);

#define S21 5
#define S22 9
#define S23 14
#define S24 20
	GG ( a, b, c, d, in[ 1], S21, 4129170786UL);
	GG ( d, a, b, c, in[ 6], S22, 3225465664UL);
	GG ( c, d, a, b, in[11], S23,	643717713);
	GG ( b, c, d, a, in[ 0], S24, 3921069994UL);
	GG ( a, b, c, d, in[ 5], S21, 3593408605UL);
	GG ( d, a, b, c, in[10], S22,	38016083);
	GG ( c, d, a, b, in[15], S23, 3634488961UL);
	GG ( b, c, d, a, in[ 4], S24, 3889429448UL);
	GG ( a, b, c, d, in[ 9], S21,	568446438);
	GG ( d, a, b, c, in[14], S22, 3275163606UL);
	GG ( c, d, a, b, in[ 3], S23, 4107603335UL);
	GG ( b, c, d, a, in[ 8], S24, 1163531501);
	GG ( a, b, c, d, in[13], S21, 2850285829UL);
	GG ( d, a, b, c, in[ 2], S22, 4243563512UL);
	GG ( c, d, a, b, in[ 7], S23, 1735328473);
	GG ( b, c, d, a, in[12], S24, 2368359562UL);

#define S31 4
#define S32 11
#define S33 16
#define S34 23
	HH ( a, b, c, d, in[ 5], S31, 4294588738UL);
	HH ( d, a, b, c, in[ 8], S32, 2272392833UL);
	HH ( c, d, a, b, in[11], S33, 1839030562);
	HH ( b, c, d, a, in[14], S34, 4259657740UL);
	HH ( a, b, c, d, in[ 1], S31, 2763975236UL);
	HH ( d, a, b, c, in[ 4], S32, 1272893353);
	HH ( c, d, a, b, in[ 7], S33, 4139469664UL);
	HH ( b, c, d, a, in[10], S34, 3200236656UL);
	HH ( a, b, c, d, in[13], S31,	681279174);
	HH ( d, a, b, c, in[ 0], S32, 3936430074UL);
	HH ( c, d, a, b, in[ 3], S33, 3572445317UL);
	HH ( b, c, d, a, in[ 6], S34,	76029189);
	HH ( a, b, c, d, in[ 9], S31, 3654602809UL);
	HH ( d, a, b, c, in[12], S32, 3873151461UL);
	HH ( c, d, a, b, in[15], S33,	530742520);
	HH ( b, c, d, a, in[ 2], S34, 3299628645UL);

#define S41 6
#define S42 10
#define S43 15
#define S44 21
	II ( a, b, c, d, in[ 0], S41, 4096336452UL);
	II ( d, a, b, c, in[ 7], S42, 1126891415);
	II ( c, d, a, b, in[14], S43, 2878612391UL);
	II ( b, c, d, a, in[ 5], S44, 4237533241UL);
	II ( a, b, c, d, in[12], S41, 1700485571);
	II ( d, a, b, c, in[ 3], S42, 2399980690UL);
	II ( c, d, a, b, in[10], S43, 4293915773UL);
	II ( b, c, d, a, in[ 1], S44, 2240044497UL);
	II ( a, b, c, d, in[ 8], S41, 1873313359);
	II ( d, a, b, c, in[15], S42, 4264355552UL);
	II ( c, d, a, b, in[ 6], S43, 2734768916UL);
	II ( b, c, d, a, in[13], S44, 1309151649);
	II ( a, b, c, d, in[ 4], S41, 4149444226UL);
	II ( d, a, b, c, in[11], S42, 3174756917UL);
	II ( c, d, a, b, in[ 2], S43,	718787259);
	II ( b, c, d, a, in[ 9], S44, 3951481745UL);

	buf[0] += a;
	buf[1] += b;
	buf[2] += c;
	buf[3] += d;
}


void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) {

	UINT4 in[16];
	int mdi;
	unsigned int i, ii;

	mdi = (int)((mdContext->i[0] >> 3) & 0x3F);

	if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
	mdContext->i[1]++;
	mdContext->i[0] += ((UINT4)inLen << 3);
	mdContext->i[1] += ((UINT4)inLen >> 29);

	while (inLen--) {
		mdContext->in[mdi++] = *inBuf++;
	 
		if (mdi == 0x40) {
			for (i = 0, ii = 0; i < 16; i++, ii += 4)
				in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
					(((UINT4)mdContext->in[ii+2]) << 16) |
					(((UINT4)mdContext->in[ii+1]) << 8) |
					((UINT4)mdContext->in[ii]);
			Transform (mdContext->buf, in);
			mdi = 0;
	 	}
	}
}


void MD5Final (MD5_CTX *mdContext) {

	UINT4 in[16];
	int mdi;
	unsigned int i, ii;
	unsigned int padLen;

	in[14] = mdContext->i[0];
	in[15] = mdContext->i[1];

	mdi = (int)((mdContext->i[0] >> 3) & 0x3F);

	padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
	MD5Update (mdContext, PADDING, padLen);

	for (i = 0, ii = 0; i < 14; i++, ii += 4)
		in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
				(((UINT4)mdContext->in[ii+2]) << 16) |
				(((UINT4)mdContext->in[ii+1]) << 8) |
				((UINT4)mdContext->in[ii]);
	
	Transform (mdContext->buf, in);

	for (i = 0, ii = 0; i < 4; i++, ii += 4) {
		mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
		mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
		mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
		mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
	}
}


static void MDPrint (MD5_CTX *mdContext) {

	sprintf(master_pass,"%02x%02x%02x%02x", 
			mdContext->digest[0], 
			mdContext->digest[1],
			mdContext->digest[2],
			mdContext->digest[3]);
}

...


int main (int argn, char **argv) 
{

	if (argn < 2)
		 usage(*argv);
		 
	MDString(*(++argv));

	printf("\nPassword Master: %s\n\n", master_pass);
	return 0;
}

运行结果:

Linux C/C++实现随机密码生成器_第2张图片

使用openssl生成密码

Linux中有几种方法可以为Linux命令行创建和生成密码。我们正在尝试的第一个方法是使用openssl。用于生成更强密码的命令包括openssl rand函数。这将帮助我们在一个字符串中生成14个随机字符。命令是:

openssl rand -base64 14

结果将是一个14个字符的强密码,如下所示。

#include 
#include 
...
static char symbols[] = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
    'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'S',
    'R', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
    'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
    'l', 'm', 'n', 'o', 'p', 'q', 's', 'r', 'u',
    'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4',
    '5', '6', '7', '8', '9', '0', '!', '~', '@',
    '#', '$', '%', '<', '>', ';', '^', '&', '*',
    '(', ')', '-', '+', '=', '_', '?', '|', '/'
};


int get_random_ascii_string(char *str, size_t in_size, generator_mode_t mode) {

...

    switch (mode) 
    {
        case FULL_ASCII_MODE:
            boundary = sizeof(symbols);
            break;
        case SHORT_ASCII_MODE:
            boundary = sizeof(symbols) - 21;
            break;
        default:
            return EXIT_FAILURE;
    } 

    if (gen_random_bytes(buffer, in_size) != EXIT_SUCCESS) 
    {
        return EXIT_FAILURE;
    }

    for (size_t i = 0; i < in_size; ++i) 
    {
        index = buffer[i];
        /* 转换间隔的随机数 */
        index %= boundary;
        str[i] = symbols[index];
        if ((i + 1) == in_size) {
            str[(i + 1)] = '\0';
        }
    }
    ...
}

int main(int argc, char *const argv[]) 
{
	...

    rv = parse_argv(argc, argv);
    if (rv) 
	{
        fprintf(stderr, "openssl_pg: invalid option -- \"%s\"\n", argv[rv]);
        show_help_info();
        return 1;
    }



    if (show_help) 
	{
        show_help_info();
        return 0;
   }

    if (!result_len) 
	{
        fprintf(stderr, "You need to specify password length\n");
        return 1;
    }
    else if (result_len < 0) 
	{
        fprintf(stderr, "Password length must be positive number\n");
        return 1;
    }
    else if (result_len > MAX_PASSWDLEN) 
	{
        fprintf(stderr, "Length of password is too big.\n");
        return 1;
    }

    if (without_spec) 
	{
        err = get_random_ascii_string(buf, result_len, SHORT_ASCII_MODE);
    }
    else 
	{
        err = get_random_ascii_string(buf, result_len, FULL_ASCII_MODE);
    }

    if (err != EXIT_SUCCESS) 
	{
        fprintf(stderr, "Failed to generate random bytes.\n");
        return EXIT_FAILURE;
    }

    fprintf(stdout, "%s\n", buf);

    explicit_memzero(buf, result_len);

    ...
}

运行结果:

If you need the complete source code, please add the WeChat number (c17865354792)

总结

我们讨论了几个从Linux命令行生成密码的方法。在本文中,我们讨论了实用程序openssh、urandom、md5sum、sha256sum。所有这些命令都可以保证从Linux命令行生成更强的密码,并且对用户确保系统安全非常有用。

Welcome to follow WeChat official account【程序猿编码

你可能感兴趣的:(C/C++,linux,c语言,c++,密码生成器,openssl)