このコミットが含まれているのは:
守矢諏訪子 2023-12-01 02:25:27 +09:00
コミット 75890ee790
10個のファイルの変更193行の追加15行の削除

ファイルの表示

@ -1,2 +1,9 @@
# 1.1.0
* TOTP対応
* READMEファイルで使い方を詳しく説明する
* zshキャプチャー
* パスワード追加関数を安定化
* パスワード表示とパスワードのコピー関数で、GNU Passで保存したパスワードの場合は改行を追加しない様に
# 1.0.0
* 最初リリース

ファイルの表示

@ -1,11 +1,11 @@
NAME=sp
VERSION=1.0.0
VERSION=1.1.0
# Linux、Haiku、かIllumos = /usr、FreeBSDかOpenBSD = /usr/local、NetBSD = /usr/pkg
PREFIX=/usr
CC=cc
FILES=main.c showpass.c yankpass.c addpass.c delpass.c listpass.c genpass.c initpass.c
FILES=main.c showpass.c yankpass.c addpass.c delpass.c listpass.c genpass.c initpass.c otppass.c
CFLAGS=-Wall -Wextra -g
LDFLAGS=-lgpgme
LDFLAGS=-lgpgme -lcrypto
all:
${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS}
@ -25,6 +25,9 @@ install: all
cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
install-zsh:
cp sp-completion.zsh /usr/share/zsh/site-functions/_sp
uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/${NAME}

ファイルの表示

@ -39,3 +39,63 @@ doas gmake install PREFIX=/usr/local
## 初期設定
「gpg -k」でGPG鍵IDを確認して、「sp -i [GPG ID]」を実行して下さい。
## 使い方
### パスワードの作成
#### 強いパスワードの場合
```sh
$ sp -g 64
nSYGSF2lWGCUsqKCRB_~mZm+spaU<zvtt%um'01$tj4h,^nB6JqX#Cm$!U+s;c7:
```
又は
```sh
$ sp -g 64 secure
nSYGSF2lWGCUsqKCRB_~mZm+spaU<zvtt%um'01$tj4h,^nB6JqX#Cm$!U+s;c7:
```
#### 弱いパスワードの場合
```sh
$ sp -g 12 risk
2aKBwb858mzg
```
### パスワードの追加
「suwako」というユーザー名の場合
```sh
$ sp -a 076.moe/suwako
パスワード:
パスワード(確認用):
パスワードを保存出来ました。
```
入力中は何も表示されないので、ご注意下さい。
### パスワードの表示
```sh
$ sp -s 076.moe/suwako
nSYGSF2lWGCUsqKCRB_~mZm+spaU<zvtt%um'01$tj4h,^nB6JqX#Cm$!U+s;c7:
```
表示せずコピーする場合は、「sp -y 076.moe/suwako」を使用して下さい。
### パスワードの削除
```sh
$ sp -d 076.moe/suwako
パスワード「076.moe/suwako」を本当に削除する事が宜しいでしょうか? (y/N): y
パスワードを削除しました。
```
## TOTP(ワンタイムパスワード)
### QRコードから
QRコードをダウンロードし、zbarimgを使用して「QR-Code:」以降の部分をコピーし、spに追加して下さい。\
`sp -a`を実行すると、「パスワード」を聞かれますが、TOTPの場合は「otpauth://」から始まる文字列をコピペして下さい。
```sh
$ zbarimg -q gitler.png
QR-Code:otpauth://totp/Gitler%20%28gitler.moe%29:suwako?algorithm=SHA1&digits=6&issuer=Gitler%20%28gitler.moe%29&period=30&secret=
$ sp -a gitler-otp
パスワード:
パスワード(確認用):
パスワードを保存出来ました。
$ sp -q gitler-otp
123456
```

ファイルの表示

@ -57,13 +57,20 @@ void getpasswd(char* prompt, char*pw, size_t pwlen) {
tcsetattr(fileno(stdin), TCSANOW, &new);
// パスワードを読み込む
fgets(pw, pwlen, stdin);
if (fgets(pw, pwlen, stdin) != NULL) {
// あれば、改行を取り消す
size_t len = strlen(pw);
if (len > 0 && pw[len - 1] == '\n') {
pw[len - 1] = '\0';
} else {
// 掃除
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
}
// 端末設定をもとに戻す
tcsetattr(fileno(stdin), TCSANOW, &old);
// 改行文字を取り消す
pw[strcspn(pw, "\n")] = 0;
}
void addpass(char* file) {
@ -233,8 +240,14 @@ void addpass(char* file) {
char buffer[512];
ssize_t read_bytes;
while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, 1, read_bytes, gpgfile);
if (fwrite(buffer, 1, (size_t)read_bytes, gpgfile) != (size_t)read_bytes) {
perror("パスワードを書き込みに失敗");
free(gpgpath);
cleanup(ctx, key[0], in, out);
return;
}
}
// 掃除

8
main.c
ファイルの表示

@ -12,11 +12,11 @@
#include "addpass.h"
#include "delpass.h"
#include "genpass.h"
void otppass(char* file);
#include "otppass.h"
void helpme();
const char* sofname = "sp";
const char* version = "1.0.0";
const char* version = "1.1.0";
void helpme() {
printf(" sp - シンプルなパスワードマネージャー\n");
@ -29,7 +29,7 @@ void helpme() {
printf("%s -a <パスワード名> :パスワードを追加\n", sofname);
printf("%s -d <パスワード名> :パスワードを削除\n", sofname);
printf("%s -g <文字数> [risk|secure] 希望文字数でパスワードをランダムに作成する。risk英数字のみ(不安)、secure英数字特別文字(デフォルト)を使用\n", sofname);
/* printf("%s -o <パスワード名>\n ワンタイムパスワード(TOTP)を表示。存在しなければ、創作する", sofname); */
printf("%s -o <パスワード名>\n ワンタイムパスワード(TOTP)を表示。存在しなければ、創作する\n", sofname);
printf("%s -h :ヘルプを表示\n", sofname);
printf("%s -v :バージョンを表示\n", sofname);
}
@ -64,7 +64,7 @@ int main (int argc, char* argv[]) {
else if (argc == 4 && strcmp(argv[3], "secure") == 0) genpass(atoi(argv[2]), true);
else helpme();
}
else if (argc == 3 && strcmp(argv[1], "-o") == 0) printf("TODO: otp\n");
else if (argc == 3 && strcmp(argv[1], "-o") == 0) otppass(argv[2]);
else if (argc == 2 && strcmp(argv[1], "-v") == 0) printf("%s-%s\n", sofname, version);
else helpme();

26
otppass.c ノーマルファイル
ファイルの表示

@ -0,0 +1,26 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <openssl/hmac.h>
unsigned long generate_totp(const unsigned char* secret, size_t keylen) {
unsigned long timestep = time(NULL) / 30;
unsigned char hmacres[20];
HMAC(EVP_sha1(), secret, keylen, (unsigned char*)&timestep, sizeof(timestep), hmacres, NULL);
int offset = hmacres[19] & 0xF;
unsigned long trunhash = (hmacres[offset] & 0x7F) << 24 |
(hmacres[offset + 1] & 0xFF) << 16 |
(hmacres[offset + 2] & 0xFF) << 8 |
(hmacres[offset + 3] & 0xFF);
unsigned long otp = trunhash % 1000000;
return otp;
}
void otppass(char* file) {
const char* secret = file;
unsigned long otp = generate_totp((unsigned char*)secret, strlen(secret));
printf("%06lu\n", otp);
}

6
otppass.h ノーマルファイル
ファイルの表示

@ -0,0 +1,6 @@
#ifndef OTPPASS_H
#define OTPPASS_H
void otppass(char* file);
#endif

ファイルの表示

@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <locale.h>
#include <gpgme.h>
@ -83,9 +84,17 @@ void showpass(char* file) {
gpgme_data_seek(out, 0, SEEK_SET);
char buffer[512];
ssize_t read_bytes;
bool islastnl = false;
while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer) - 1)) > 0) {
buffer[read_bytes] = '\0';
printf("%s", buffer);
fwrite(buffer, 1, read_bytes, stdout);
if (buffer[read_bytes - 1] == '\n') {
islastnl = true;
}
}
if (!islastnl) {
putchar('\n');
}
// 掃除

48
sp-completion.zsh ノーマルファイル
ファイルの表示

@ -0,0 +1,48 @@
# compdef sp
_sp () {
local state
local -a options
local -a entries
_arguments -C \
'-i[GPGと使ってパスワードストレージを初期設定]: :_sp_complete_keys' \
'-s[パスワードを表示]: :_sp_complete_entries' \
'-y[パスワードを表示せずクリップボードにコピーする]: :_sp_complete_entries' \
'-l[パスワード一覧を表示]' \
'-a[パスワードを追加]: :_sp_complete_entries' \
'-d[パスワードを削除]: :_sp_complete_entries' \
'-g[希望文字数でパスワードをランダムに作成する]: :_sp_complete_entries' \
'-o[ワンタイムパスワード(TOTP)を表示]: :_sp_complete_entries' \
'-h[ヘルプを表示]' \
'-v[バージョンを表示]' \
'*:: :->subcmds'
case $state in
subcmds)
_message "no more arguments"
;;
esac
}
_sp_cmd_show () {
_sp_complete_entries
}
_sp_complete_entries() {
_sp_complete_entries_helper -type f
}
_sp_complete_entries_helper () {
local IFS=$'\n'
local prefix="${SP_DIR:-$HOME/.local/share/sp}"
entries=("${(f)$(find -L "$prefix" \( -name .git -o -name .gpg-id \) -prune -o -type f -print 2>/dev/null | sed -e "s#${prefix}/##" -e 's#\.gpg$##')}")
_describe 'password entries' entries
}
_sp_complete_keys () {
local IFS=$'\n'
_values 'gpg keys' $(gpg2 --list-secret-keys --with-colons | cut -d : -f 10 | sort -u | sed '/^$/d')
}
compdef _sp sp

ファイルの表示

@ -98,12 +98,18 @@ void yankpass(char* file) {
char buffer[512];
ssize_t read_bytes;
while ((read_bytes = gpgme_data_read(out, buffer, 511)) > 0) {
while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer))) > 0) {
if (buffer[read_bytes - 1] == '\n') {
read_bytes--;
}
fwrite(buffer, 1, read_bytes, pipe);
}
pclose(pipe);
// 45秒後、クリップボードから削除する
printf("パスワードをクリップボードに追加しました。\n45秒後はクリップボードから取り消されます。\n");
sleep(45);
system("echo -n | xclip -selection clipboard");