Skip to content

Instantly share code, notes, and snippets.

@bdd
Last active August 18, 2021 19:43
Show Gist options
  • Save bdd/1115291 to your computer and use it in GitHub Desktop.
Save bdd/1115291 to your computer and use it in GitHub Desktop.
Generate a key from a passpharse w/ PBKDF2
/*
* Copyright (c) 2011 Berk D. Demir <bdd@mindcast.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* OpenSSL doesn't provide a userland tool for PBKDF2.
*
* I recently needed this for supplying Crashplan my own encryption key
* for its Blowfish cipher.
*
* Sadly I realized their passphrase implementation was simply padding the
* password to 448-bits and storing it in base64. Sigh...
*
* This small piece of code gets password, salt, number of iterations and
* desired key length in bytes and outputs HMAC SHA1 backed PBKDF2 function
* output to stdout as binary.
*
* Use pipes or shell i/o redirection to make the output useful.
*
* e.g.
* % pbkdf2 password salt 1024 56 > bf448.key
*
* % pbkdf2 password salt 1024 56 | openssl base64
*
*/
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <openssl/evp.h>
int
main(int argc, char *argv[])
{
const char *usage = "usage: %s <password> <salt> <iterations> <keylen>";
const char *errstr_notint = "\"%s\" is not a decimal integer.";
unsigned char *out;
const char *pass, *salt;
int iter, keylen;
if (argc != 5)
errx(1, usage, argv[0]);
pass = argv[1];
salt = argv[2];
iter = (int)strtol(argv[3], (char **)NULL, 10);
keylen = (int)strtol(argv[4], (char **)NULL, 10);
if (errno != 0) { /* strtol failed */
if (iter == 0)
warnx(errstr_notint, argv[3]);
if (keylen == 0)
warnx(errstr_notint, argv[4]);
errx(1, usage, argv[0]);
}
out = malloc(keylen);
if (out == NULL)
err(1, "Couldn't allocate memory.");
/* always returns 1 */
PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass),
salt, strlen(salt),
iter, keylen,
out);
if (write(1, out, keylen) == -1)
return 1;
else
return 0;
}
@andermoran
Copy link

passing 'const char *' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]

@blackandred
Copy link

I wrote similar application in GO: https://github.com/riotkit-org/gpbkdf2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment