mirror of
https://github.com/angt/secret
synced 2024-12-27 21:58:42 +01:00
Add command pass
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
parent
9c68796f3e
commit
d771c320f3
2 changed files with 57 additions and 11 deletions
12
README.md
12
README.md
|
@ -10,6 +10,7 @@ Keep your little secrets, publicly.
|
|||
- No configuration. Get back your file and you're done.
|
||||
- Secret's name (hostname, mail, login, etc.) are also encrypted.
|
||||
- Secret agent only trusts subprocesses. Not all user processes! How nice is that?
|
||||
- Unstored secrets! Derived from a simple key and a passphrase.
|
||||
- Supports multiple passphrases. Not super user-friendly but nice to have.
|
||||
- Depends only on the [libhydrogen](https://libhydrogen.org/) library.
|
||||
- Small, simple and non obfuscated C code. Well, I hope so :)
|
||||
|
@ -46,6 +47,7 @@ Available commands:
|
|||
set Set a new secret
|
||||
renew Regenerate an existing secret
|
||||
reset Update an existing secret
|
||||
pass Derivate a new secret
|
||||
agent Run a process in a trusted zone
|
||||
version Show version
|
||||
|
||||
|
@ -64,13 +66,19 @@ Add a new randomly generated secret:
|
|||
|
||||
$ secret new test
|
||||
Passphrase:
|
||||
9{6u0ue>5&W2+z#OR:`X<@-#
|
||||
^>f.8%]_zoN^jSi0CO_{(yYY5
|
||||
|
||||
Show the secret:
|
||||
|
||||
$ secret show test
|
||||
Passphrase:
|
||||
9{6u0ue>5&W2+z#OR:`X<@-#
|
||||
^>f.8%]_zoN^jSi0CO_{(yYY5
|
||||
|
||||
Derive a deterministic (a.k.a. unstored) secret:
|
||||
|
||||
$ secret pass me@domain.com
|
||||
Passphrase:
|
||||
a`4$B2mJ=|"HD?b4:/y"?wOaQ
|
||||
|
||||
Storing binary secrets is supported:
|
||||
|
||||
|
|
56
secret.c
56
secret.c
|
@ -22,6 +22,7 @@
|
|||
#define S_VER_MAJOR 0U
|
||||
#define S_VER_MINOR 1U
|
||||
#define S_ENTRYSIZE 512U
|
||||
#define S_PWDGENLEN 25U
|
||||
#define S_ENV_AGENT "SECRET_AGENT"
|
||||
#define S_ENV_STORE "SECRET_STORE"
|
||||
|
||||
|
@ -46,10 +47,12 @@ struct {
|
|||
uint8_t enc[S_ENTRYSIZE];
|
||||
char ctx_master[hydro_pwhash_CONTEXTBYTES];
|
||||
char ctx_secret[hydro_secretbox_CONTEXTBYTES];
|
||||
char ctx_passwd[hydro_pwhash_CONTEXTBYTES];
|
||||
} s = {
|
||||
.pipe = {-1, -1},
|
||||
.ctx_master = "MASTER",
|
||||
.ctx_secret = "SECRET",
|
||||
.ctx_passwd = "PASSWD",
|
||||
};
|
||||
|
||||
_Noreturn static void
|
||||
|
@ -87,6 +90,13 @@ s_fatal(const char *fmt, ...)
|
|||
s_exit(1);
|
||||
}
|
||||
|
||||
_Noreturn static void
|
||||
s_oops(const int line)
|
||||
{
|
||||
s_fatal("Oops at line %i", line);
|
||||
s_exit(2);
|
||||
}
|
||||
|
||||
static size_t
|
||||
s_read(int fd, void *data, size_t size)
|
||||
{
|
||||
|
@ -223,7 +233,7 @@ s_open_secret(int use_tty)
|
|||
hydro_memzero(pass, sizeof(pass));
|
||||
|
||||
if (r)
|
||||
s_fatal("Call of the Jedi...");
|
||||
s_oops(__LINE__);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
@ -240,7 +250,7 @@ s_print_keys(int use_tty)
|
|||
continue;
|
||||
size_t len = strnlen(s.x.entry.msg, sizeof(s.x.entry.msg));
|
||||
if (len >= sizeof(s.x.entry.msg))
|
||||
s_fatal("Luckily I was paranoid...");
|
||||
s_oops(__LINE__);
|
||||
s_write(1, s.x.entry.msg, len);
|
||||
s_write(1, "\n", 1);
|
||||
}
|
||||
|
@ -356,6 +366,16 @@ s_help_keys(int argc, char **argv, int print_keys)
|
|||
s_exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
s_normalize_and_show(unsigned char *buf, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buf[i] = '!' + buf[i] % (1U + '~' - '!');
|
||||
|
||||
s_write(1, buf, size);
|
||||
if (isatty(1)) s_write(1, "\n", 1);
|
||||
}
|
||||
|
||||
struct s_op {
|
||||
int create;
|
||||
int generate;
|
||||
|
@ -375,17 +395,12 @@ s_do(int argc, char **argv, void *data)
|
|||
s_get_secret(fd, argv[1], op->create);
|
||||
|
||||
unsigned char secret[S_ENTRYSIZE];
|
||||
size_t len = 25;
|
||||
size_t len = S_PWDGENLEN;
|
||||
|
||||
if (op->generate) {
|
||||
hydro_memzero(secret, sizeof(secret));
|
||||
hydro_random_buf(secret, len);
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
secret[i] = '!' + secret[i] % (1U + '~' - '!');
|
||||
|
||||
s_write(1, secret, len);
|
||||
if (isatty(1)) s_write(1, "\n", 1);
|
||||
s_normalize_and_show(secret, len);
|
||||
} else {
|
||||
len = isatty(0) ? s_input(secret, sizeof(secret), "Secret: ")
|
||||
: s_read(0, secret, sizeof(secret));
|
||||
|
@ -417,6 +432,28 @@ s_show(int argc, char **argv, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
s_pass(int argc, char **argv, void *data)
|
||||
{
|
||||
s_help_keys(argc, argv, 0);
|
||||
|
||||
if (argc != 2)
|
||||
return argc;
|
||||
|
||||
close(s_open_secret(1));
|
||||
|
||||
unsigned char secret[S_PWDGENLEN];
|
||||
int r = hydro_pwhash_deterministic(secret, sizeof(secret),
|
||||
argv[1], strlen(argv[1]),
|
||||
s.ctx_passwd, s.x.key,
|
||||
load64_le(s.hdr.opslimit), 0, 1);
|
||||
if (r)
|
||||
s_oops(__LINE__);
|
||||
|
||||
s_normalize_and_show(secret, sizeof(secret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
s_cloexec(int fd)
|
||||
{
|
||||
|
@ -622,6 +659,7 @@ main(int argc, char **argv)
|
|||
{"set", "Set a new secret", &s_do, &s_set, .grp = 1},
|
||||
{"renew", "Regenerate an existing secret", &s_do, &s_rnw, .grp = 1},
|
||||
{"reset", "Update an existing secret", &s_do, &s_rst, .grp = 1},
|
||||
{"pass", "Derivate a new secret", &s_pass, NULL, .grp = 1},
|
||||
{"agent", "Run a process in a trusted zone", &s_agent, NULL, .grp = 1},
|
||||
{"version", "Show version", &s_version, NULL, .grp = 1},
|
||||
{0}};
|
||||
|
|
Loading…
Reference in a new issue