mirror of
https://github.com/angt/secret
synced 2025-01-30 08:34:28 +01:00
Allow binary secrets
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
parent
a5d3dd5b4f
commit
b83f26bb36
2 changed files with 48 additions and 28 deletions
12
README.md
12
README.md
|
@ -72,6 +72,18 @@ Show the secret:
|
|||
Passphrase:
|
||||
9{6u0ue>5&W2+z#OR:`X<@-#
|
||||
|
||||
Storing binary secrets is supported:
|
||||
|
||||
$ dd if=/dev/urandom bs=1 count=32 bs=1 2>/dev/null | secret set mykey
|
||||
Passphrase:
|
||||
|
||||
Then, use a pipe to get it:
|
||||
|
||||
$ secret show mykey | xxd
|
||||
Passphrase:
|
||||
00000000: 0ee9 cdb3 de0a 3e71 b623 726d 5d7e eb23 ......>q.#rm]~.#
|
||||
00000010: 5b43 a458 3fb7 3b96 ea9b 6e47 d302 cae7 [C.X?.;...nG....
|
||||
|
||||
Start a trusted zone:
|
||||
|
||||
$ secret agent
|
||||
|
|
64
secret.c
64
secret.c
|
@ -39,7 +39,10 @@ struct {
|
|||
} hdr;
|
||||
struct {
|
||||
uint8_t key[hydro_secretbox_KEYBYTES];
|
||||
char msg[S_ENTRYSIZE - hydro_secretbox_HEADERBYTES];
|
||||
struct {
|
||||
uint8_t slen[2];
|
||||
char msg[S_ENTRYSIZE - hydro_secretbox_HEADERBYTES - 2U];
|
||||
} entry;
|
||||
} x;
|
||||
uint8_t enc[S_ENTRYSIZE];
|
||||
char ctx_master[hydro_pwhash_CONTEXTBYTES];
|
||||
|
@ -168,7 +171,7 @@ s_input(unsigned char *buf, size_t size, const char *prompt)
|
|||
s_fatal("Invalid input!");
|
||||
}
|
||||
|
||||
memset(buf + len, 0, size - len);
|
||||
hydro_memzero(buf + len, size - len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -234,11 +237,14 @@ s_print_keys(int use_tty)
|
|||
int fd = s_open_secret(use_tty);
|
||||
|
||||
while (s_read(fd, s.enc, sizeof(s.enc)) == sizeof(s.enc)) {
|
||||
if (hydro_secretbox_decrypt(s.x.msg,
|
||||
if (hydro_secretbox_decrypt(&s.x.entry,
|
||||
s.enc, sizeof(s.enc), 0,
|
||||
s.ctx_secret, s.x.key))
|
||||
continue;
|
||||
s_write(1, s.x.msg, strnlen(s.x.msg, sizeof(s.x.msg)));
|
||||
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_write(1, s.x.entry.msg, len);
|
||||
s_write(1, "\n", 1);
|
||||
}
|
||||
close(fd);
|
||||
|
@ -246,39 +252,36 @@ s_print_keys(int use_tty)
|
|||
}
|
||||
|
||||
static size_t
|
||||
s_valid(const char *str)
|
||||
s_keylen(const char *str)
|
||||
{
|
||||
if (!str)
|
||||
return 0;
|
||||
s_fatal("Empty key!");
|
||||
|
||||
for (size_t i = 0; i < 256; i++) {
|
||||
if (!str[i])
|
||||
return i;
|
||||
if (str[i] < '!' || str[i] > '~')
|
||||
return 0;
|
||||
if (str[i] > 0 && str[i] < ' ')
|
||||
s_fatal("Malformed key");
|
||||
}
|
||||
return 0;
|
||||
s_fatal("Key too big!");
|
||||
}
|
||||
|
||||
static const char *
|
||||
s_get_secret(int fd, const char *key, int create)
|
||||
{
|
||||
size_t len = s_valid(key);
|
||||
|
||||
if (!len)
|
||||
s_fatal("Secret %s is malformed", key);
|
||||
size_t len = s_keylen(key);
|
||||
|
||||
while (s_read(fd, s.enc, sizeof(s.enc)) == sizeof(s.enc)) {
|
||||
if (hydro_secretbox_decrypt(s.x.msg,
|
||||
if (hydro_secretbox_decrypt(&s.x.entry,
|
||||
s.enc, sizeof(s.enc), 0,
|
||||
s.ctx_secret, s.x.key))
|
||||
continue;
|
||||
if (hydro_equal(s.x.msg, key, len + 1)) {
|
||||
if (hydro_equal(s.x.entry.msg, key, len + 1)) {
|
||||
if (create)
|
||||
s_fatal("Secret %s exists!", key);
|
||||
if (lseek(fd, -(off_t)sizeof(s.enc), SEEK_CUR) == (off_t)-1)
|
||||
s_fatal("seek: %s", strerror(errno));
|
||||
return &s.x.msg[len + 1];
|
||||
return &s.x.entry.msg[len + 1];
|
||||
}
|
||||
}
|
||||
if (!create)
|
||||
|
@ -288,17 +291,20 @@ s_get_secret(int fd, const char *key, int create)
|
|||
}
|
||||
|
||||
static void
|
||||
s_set_secret(int fd, const char *id, const unsigned char *secret)
|
||||
s_set_secret(int fd, const char *key, const unsigned char *secret, size_t slen)
|
||||
{
|
||||
memset(&s.x.msg, 0, sizeof(s.x.msg));
|
||||
size_t len = s_keylen(key);
|
||||
|
||||
int ret = snprintf(s.x.msg, sizeof(s.x.msg), "%s%c%s", id, 0, secret);
|
||||
|
||||
if (ret <= 0 || (size_t)ret >= sizeof(s.x.msg))
|
||||
if (len + slen + 1 > sizeof(s.x.entry.msg))
|
||||
s_fatal("Entry too big!");
|
||||
|
||||
hydro_memzero(&s.x.entry, sizeof(s.x.entry));
|
||||
store16_le(s.x.entry.slen, slen);
|
||||
memcpy(s.x.entry.msg, key, len);
|
||||
memcpy(s.x.entry.msg + len + 1, secret, slen);
|
||||
|
||||
hydro_secretbox_encrypt(s.enc,
|
||||
s.x.msg, sizeof(s.x.msg), 0,
|
||||
&s.x.entry, sizeof(s.x.entry), 0,
|
||||
s.ctx_secret, s.x.key);
|
||||
|
||||
s_write(fd, s.enc, sizeof(s.enc));
|
||||
|
@ -372,23 +378,25 @@ 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;
|
||||
|
||||
if (op->generate) {
|
||||
size_t len = 25;
|
||||
hydro_memzero(secret, sizeof(secret));
|
||||
hydro_random_buf(secret, len);
|
||||
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
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);
|
||||
} else {
|
||||
if (!s_input(secret, sizeof(secret), "Secret: "))
|
||||
s_exit(0);
|
||||
len = isatty(0) ? s_input(secret, sizeof(secret), "Secret: ")
|
||||
: s_read(0, secret, sizeof(secret));
|
||||
}
|
||||
if (!len)
|
||||
s_exit(0);
|
||||
|
||||
s_set_secret(fd, argv[1], secret);
|
||||
s_set_secret(fd, argv[1], secret, len);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -405,7 +413,7 @@ s_show(int argc, char **argv, void *data)
|
|||
const char *secret = s_get_secret(fd, argv[1], 0);
|
||||
|
||||
if (secret) {
|
||||
s_write(1, secret, strlen(secret));
|
||||
s_write(1, secret, load16_le(s.x.entry.slen));
|
||||
if (isatty(1)) s_write(1, "\n", 1);
|
||||
}
|
||||
close(fd);
|
||||
|
|
Loading…
Add table
Reference in a new issue