【问题标题】:crypt in c++ returning different strings(or no string at all)C++中的crypt返回不同的字符串(或根本没有字符串)
【发布时间】:2018-05-28 12:35:18
【问题描述】:

我正在尝试创建一个类似 shadowfile 的 txt 文件,并且我正在使用 crypt 来生成哈希。我通过终端询问密码,然后生成一个伪随机盐。我在 crypt 函数中给出了这两个值,但它每次都创建一个不同的哈希值,或者根本没有创建一个不同的哈希值,我无法理解我的代码有什么问题。

#include<stdio.h>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<ctime>
#include<crypt.h>
#include<unistd.h>


using namespace std;

/*====== READ STRING DYNAMICALLY ======*/

char* readFromTerminal() {

    int length = 0; //counts number of characters
    char c; //holds last read character
    char *input;

    input = (char *) malloc(sizeof (char)); //Allocate initial memory

    if (input == NULL) //Fail if allocating of memory not possible
    {
        printf("Could not allocate memory!");
        exit(1);
    }

    while ((c = getchar()) != '\n') //until end of line
    {
        realloc(input, (sizeof (char))); //allocate more memory
        input[length++] = c; //save entered character
    }

    input[length] = '\0'; //add terminator
    return input;
}

/*====== GENERATE PSEUDO RANDOM SALT VALUE ======*/

char* generateSalt() {

    const char alphanum[] =
            "0123456789"
            "!@#$%^&*"
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz"; //salt alphanum

    int alphanumLength = sizeof (alphanum) - 1; // alphanum lenght

    char *salt; //salt string

    salt = (char *) malloc(sizeof (char)); //Allocate initial memory

    if (salt == NULL) //Fail if allocating of memory not possible
    {
        printf("Could not allocate memory!");
        exit(1);
    }

    srand(time(NULL));

    for (int i = 0; i < 21; i++) {
        realloc(salt, (sizeof (char))); //allocate more memory

        salt[i] = alphanum[rand() % alphanumLength]; //generate a random character from the alphanum
    }

    salt[21] = '\0'; //add terminator

    return salt;
}

/*====== MAIN ======*/
int main(int argc, char** argv) {

    char *username, *password, *salt, *hash;

    ofstream myshadow("myshadow.txt", ios::out);

    cout << "Enter your username: ";
    username = readFromTerminal();
    cout << "Enter your password: ";
    password = readFromTerminal();

    salt = generateSalt();
    hash = (char *) malloc(30 * sizeof (char)); //Allocate memory for hash
    hash = crypt(password, salt);

    myshadow << username << ":" << hash;
    return 0;
}

【问题讨论】:

  • 为什么这个标签是C
  • 现在对你来说不是个大问题
  • 每次使用当前时间作为种子 (srand(time(NULL));),所以很明显每次都有不同的哈希值(即每次使用不同的盐)。
  • 这很正常。如果你改变盐,哈希值也会改变。
  • 当它什么都不生产的时候呢?

标签: c++ linux crypt


【解决方案1】:

这里有很多需要改进的地方!

  • 当 C++ 带有 std::string 时,你使用原始的 char *
  • 您使用显式的mallocrealloc 更不用说认为问题很快就会出现

手动内存管理需要非常谨慎的编程。这里的错误是由realloc 的错误使用引起的:size 参数给出了新的 total 分配大小,而不是增量。因此,您应该跟踪分配的大小,增加它并使用该新值调用 realloc。由于realloc 可能会返回一个新的内存块,您应该始终使用:

input = (char *) realloc(input, new_size);

顺便说一句,generateSalt 中的等效问题...

但由于std::getline,所有内容都已包含在 C++ 中!此外,&lt;random&gt; 模块带有强大的生成器,当旧的 rand 遭受许多默认值时(仅 google 用于 rand vs. random

所以代码可以精简为:

include<iostream>
#include<fstream>
#include<unistd.h>
#include <random>


using namespace std;

std::string generateSalt() {

    const char alphanum[] =
            "0123456789"
            "!@#$%^&*"
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz"; //salt alphanum

    std::random_device rd;  //Will be used to obtain a seed for the random number engine
    std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
    std::uniform_int_distribution<> dis(0, sizeof(alphanum)-1); //Uniform distribution on an interval
    char salt[22];          // 21 useful characters in salt (as in original code)
    for(char& c: salt) {
        c = alphanum[dis(gen)];
    }
    salt[21] = 0;
    return std::string(salt);
}

/*====== MAIN ======*/
int main(int argc, char** argv) {

    string username, password, salt, hash;

    ofstream myshadow("myshadow.txt", ios::out);

    cout << "Enter your username: ";
    if (! getline(cin, username)) return 1;
    cout << "Enter your password: ";
    if (! getline(cin, password)) return 1;

    salt = generateSalt();
    hash = crypt(password.c_str(), salt.c_str());

    myshadow << username << ":" << hash;
    return 0;
}

使用 C++ 字符串的另一个好处是分配和解除分配会自动处理,无需调用free...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-13
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多