1.1.0
このコミットが含まれているのは:
コミット
75890ee790
|
@ -1,2 +1,9 @@
|
||||||
|
# 1.1.0
|
||||||
|
* TOTP対応
|
||||||
|
* READMEファイルで使い方を詳しく説明する
|
||||||
|
* zshキャプチャー
|
||||||
|
* パスワード追加関数を安定化
|
||||||
|
* パスワード表示とパスワードのコピー関数で、GNU Passで保存したパスワードの場合は改行を追加しない様に
|
||||||
|
|
||||||
# 1.0.0
|
# 1.0.0
|
||||||
* 最初リリース
|
* 最初リリース
|
||||||
|
|
9
Makefile
9
Makefile
|
@ -1,11 +1,11 @@
|
||||||
NAME=sp
|
NAME=sp
|
||||||
VERSION=1.0.0
|
VERSION=1.1.0
|
||||||
# Linux、Haiku、かIllumos = /usr、FreeBSDかOpenBSD = /usr/local、NetBSD = /usr/pkg
|
# Linux、Haiku、かIllumos = /usr、FreeBSDかOpenBSD = /usr/local、NetBSD = /usr/pkg
|
||||||
PREFIX=/usr
|
PREFIX=/usr
|
||||||
CC=cc
|
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
|
CFLAGS=-Wall -Wextra -g
|
||||||
LDFLAGS=-lgpgme
|
LDFLAGS=-lgpgme -lcrypto
|
||||||
|
|
||||||
all:
|
all:
|
||||||
${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS}
|
${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS}
|
||||||
|
@ -25,6 +25,9 @@ install: all
|
||||||
cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
|
cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
|
||||||
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
|
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||||
|
|
||||||
|
install-zsh:
|
||||||
|
cp sp-completion.zsh /usr/share/zsh/site-functions/_sp
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
|
rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||||
|
|
||||||
|
|
60
README.md
60
README.md
|
@ -39,3 +39,63 @@ doas gmake install PREFIX=/usr/local
|
||||||
|
|
||||||
## 初期設定
|
## 初期設定
|
||||||
「gpg -k」でGPG鍵IDを確認して、「sp -i [GPG ID]」を実行して下さい。
|
「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
|
||||||
|
```
|
||||||
|
|
23
addpass.c
23
addpass.c
|
@ -57,13 +57,20 @@ void getpasswd(char* prompt, char*pw, size_t pwlen) {
|
||||||
tcsetattr(fileno(stdin), TCSANOW, &new);
|
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);
|
tcsetattr(fileno(stdin), TCSANOW, &old);
|
||||||
|
|
||||||
// 改行文字を取り消す
|
|
||||||
pw[strcspn(pw, "\n")] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addpass(char* file) {
|
void addpass(char* file) {
|
||||||
|
@ -233,8 +240,14 @@ void addpass(char* file) {
|
||||||
|
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
ssize_t read_bytes;
|
ssize_t read_bytes;
|
||||||
|
|
||||||
while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer))) > 0) {
|
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
8
main.c
|
@ -12,11 +12,11 @@
|
||||||
#include "addpass.h"
|
#include "addpass.h"
|
||||||
#include "delpass.h"
|
#include "delpass.h"
|
||||||
#include "genpass.h"
|
#include "genpass.h"
|
||||||
void otppass(char* file);
|
#include "otppass.h"
|
||||||
void helpme();
|
void helpme();
|
||||||
|
|
||||||
const char* sofname = "sp";
|
const char* sofname = "sp";
|
||||||
const char* version = "1.0.0";
|
const char* version = "1.1.0";
|
||||||
|
|
||||||
void helpme() {
|
void helpme() {
|
||||||
printf("076 sp - シンプルなパスワードマネージャー\n");
|
printf("076 sp - シンプルなパスワードマネージャー\n");
|
||||||
|
@ -29,7 +29,7 @@ void helpme() {
|
||||||
printf("%s -a <パスワード名> :パスワードを追加\n", sofname);
|
printf("%s -a <パスワード名> :パスワードを追加\n", sofname);
|
||||||
printf("%s -d <パスワード名> :パスワードを削除\n", sofname);
|
printf("%s -d <パスワード名> :パスワードを削除\n", sofname);
|
||||||
printf("%s -g <文字数> [risk|secure] :希望文字数でパスワードをランダムに作成する。risk=英数字のみ(不安)、secure=英数字+特別文字(デフォルト)を使用\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 -h :ヘルプを表示\n", sofname);
|
||||||
printf("%s -v :バージョンを表示\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 if (argc == 4 && strcmp(argv[3], "secure") == 0) genpass(atoi(argv[2]), true);
|
||||||
else helpme();
|
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 if (argc == 2 && strcmp(argv[1], "-v") == 0) printf("%s-%s\n", sofname, version);
|
||||||
else helpme();
|
else helpme();
|
||||||
|
|
||||||
|
|
|
@ -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*)×tep, 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);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef OTPPASS_H
|
||||||
|
#define OTPPASS_H
|
||||||
|
|
||||||
|
void otppass(char* file);
|
||||||
|
|
||||||
|
#endif
|
13
showpass.c
13
showpass.c
|
@ -1,5 +1,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
||||||
#include <gpgme.h>
|
#include <gpgme.h>
|
||||||
|
@ -83,9 +84,17 @@ void showpass(char* file) {
|
||||||
gpgme_data_seek(out, 0, SEEK_SET);
|
gpgme_data_seek(out, 0, SEEK_SET);
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
ssize_t read_bytes;
|
ssize_t read_bytes;
|
||||||
|
bool islastnl = false;
|
||||||
|
|
||||||
while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer) - 1)) > 0) {
|
while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer) - 1)) > 0) {
|
||||||
buffer[read_bytes] = '\0';
|
fwrite(buffer, 1, read_bytes, stdout);
|
||||||
printf("%s", buffer);
|
if (buffer[read_bytes - 1] == '\n') {
|
||||||
|
islastnl = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!islastnl) {
|
||||||
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 掃除
|
// 掃除
|
||||||
|
|
|
@ -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];
|
char buffer[512];
|
||||||
ssize_t read_bytes;
|
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);
|
fwrite(buffer, 1, read_bytes, pipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
pclose(pipe);
|
pclose(pipe);
|
||||||
|
|
||||||
// 45秒後、クリップボードから削除する
|
// 45秒後、クリップボードから削除する
|
||||||
|
printf("パスワードをクリップボードに追加しました。\n45秒後はクリップボードから取り消されます。\n");
|
||||||
sleep(45);
|
sleep(45);
|
||||||
system("echo -n | xclip -selection clipboard");
|
system("echo -n | xclip -selection clipboard");
|
||||||
|
|
||||||
|
|
読み込み中…
新しいイシューから参照