0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C言語でパスワード生成プログラムを作成

0
Last updated at Posted at 2025-11-14

学習のためC言語でパスワード生成プログラムを作成した。
仕様は以下の通り。
・ランダムで初期パスワード生成後に新しいパスワードを標準入力で受け付ける。
・パスワードは数字,英字(大文字・小文字),記号を含む必要がある。
 初期パスワードと同一不可。
・記号は `~!@#$^&*()_-+={}[]|:;'<>,.?/\ が使用可能。
・パスワード文字数は8~256文字で、初期パスワードは8文字とする。

Password_create.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>

#define LENGTH_MIN 8
#define LENGTH_MAX 256

const char lower[] = "abcdefghijklmnopqrstuvwxyz";
const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char digits[] = "0123456789";
const char symbol[] ="`~!@#$^&*()_-+={}[]|:;'<>,.?/\\";

void shuffle(char *a, int n)
{
    for (int i = n - 1; i > 0; --i)
    {
        int j = rand() % (i + 1);
        char tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
}

int validate_password(char init_password[],char new_password[])
{
    if (strcmp(init_password, new_password)==0)
    {
        printf("初期パスワードと同じです。パスワードを変えて下さい。\n");
        return -1;
    }

    if (strlen(new_password) < LENGTH_MIN)
    {
        printf("文字数が少ないです。%d 文字以上必要です。\n",LENGTH_MIN);
        return -1;
    }
    else if(strlen(new_password) > LENGTH_MAX)
    {
        printf("文字数が多いです。上限 %d 文字までです。\n",LENGTH_MAX);
        return -1;
    }

    /* 種類チェック */
    int has_upper = 0;
    int has_lower = 0;
    int has_digit = 0;
    int has_symbol = 0;

    for (int i = 0; new_password[i] != '\0'; i++)
    {
        unsigned char c = (unsigned char)new_password[i];

        if (isupper(c))
            has_upper = 1;
        else if (islower(c))
            has_lower = 1;
        else if (isdigit(c))
            has_digit = 1;
        else if( strchr(symbol,new_password[i]) != NULL)
            has_symbol = 1;
        else
        {
            printf("使えない文字 %c が含まれています。\n",new_password[i]);
            return -1;
        }
    }

    /* 判定出力 */
    if (!has_upper)
        printf("英大文字が含まれていません。\n");
    if (!has_lower)
        printf("英小文字が含まれていません。\n");
    if (!has_digit)
        printf("数字が含まれていません。\n");
    if (!has_symbol)
        printf("記号が含まれていません。\n");    

    if (has_upper && has_lower && has_digit && has_symbol)
    {
        printf("有効なパスワードです\n");
        return 0;
    }
    else
        return -1;

}

int main(void)
{
    int c;
    char init_password[LENGTH_MAX + 2];
    char new_password[LENGTH_MAX + 2];
    int pos = 0;
    char pool[512];

    snprintf(pool, sizeof(pool), "%s%s%s%s", lower, upper, digits, symbol);

    srand((unsigned)time(NULL));

    /* 必須の1文字ずつを挿入 */
    init_password[pos++] = lower[rand() % (strlen(lower))];
    init_password[pos++] = upper[rand() % (strlen(upper))];
    init_password[pos++] = digits[rand() % (strlen(digits))];
    init_password[pos++] = symbol[rand() % (strlen(symbol))];

    /* 残りを全候補からランダムに埋める */
    while (pos < LENGTH_MIN)
        init_password[pos++] = pool[rand() % (strlen(pool))];

    /* 位置をランダムにシャッフルして偏りを無くす */
    shuffle(init_password, LENGTH_MIN);
    init_password[LENGTH_MIN] = '\0';

    while (1)
    {
        printf("初期パスワード: %s\n", init_password);
        printf("\n");

        printf("新しいパスワードを入力して下さい。\n");
        printf("英大文字・小文字・数字・記号をすべて含む%d~%d文字である必要があります。\n",
                LENGTH_MIN,LENGTH_MAX);
        printf("記号は `~!@#$^&*()_-+={}[]|:;'<>,.?/\\が使えます。\n");

        if (fgets(new_password, sizeof(new_password), stdin) != NULL)
        {
            size_t len = strlen(new_password);

            if (len > 0 && new_password[len - 1] == '\n') 
                new_password[len - 1] = '\0';
            else
            {
                /* 改行が無かった場合は、バッファの残りを捨てる */
                int ch;
                while ((ch = getchar()) != '\n' && ch != EOF);
            }
        }
        if(validate_password(init_password,new_password) == 0)
            break;
    }
    return 0;
}

実行結果の例を以下に示す。

./password_create
初期パスワード: W9*m$NI$

新しいパスワードを入力して下さい。
英大文字・小文字・数字・記号をすべて含む8~256文字である必要があります。
記号は `~!@#$^&*()_-+={}[]|:;'<>,.?/\が使えます。
W9*m$NI$
初期パスワードと同じです。パスワードを変えて下さい。
初期パスワード: W9*m$NI$

新しいパスワードを入力して下さい。
英大文字・小文字・数字・記号をすべて含む8~256文字である必要があります。
記号は `~!@#$^&*()_-+={}[]|:;'<>,.?/\が使えます。
W9*m$NI 
文字数が少ないです。8 文字以上必要です。
初期パスワード: W9*m$NI$

新しいパスワードを入力して下さい。
英大文字・小文字・数字・記号をすべて含む8~256文字である必要があります。
記号は `~!@#$^&*()_-+={}[]|:;'<>,.?/\が使えます。
Wa*m$NI$
数字が含まれていません。
初期パスワード: W9*m$NI$

新しいパスワードを入力して下さい。
英大文字・小文字・数字・記号をすべて含む8~256文字である必要があります。
記号は `~!@#$^&*()_-+={}[]|:;'<>,.?/\が使えます。
W9*m$NI$a
有効なパスワードです
0
0
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?