Changeset 304

Show
Ignore:
Timestamp:
11/24/05 09:53:05
Author:
ben
Message:

Create secret keys from scratch, partially implemented plaintext signing.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • openpgpsdk/trunk/configure

    r303 r304  
    3838              $Subst{INCLUDES}.=" -I $loc/include"; 
    3939              $Subst{CRYPTO_LIBS}="$loc/lib/libcrypto.a"; 
     40              # assume developer version if library isn't in .../lib 
    4041              $Subst{CRYPTO_LIBS}="$loc/libcrypto.a" 
    4142                  if !-f $Subst{CRYPTO_LIBS}; 
  • openpgpsdk/trunk/examples/Makefile.template

    r297 r304  
    99 
    1010all: Makefile lib .depend packet-dump verify create-key create-signed-key \ 
    11      verify2 
     11     verify2 sign-detached 
    1212 
    13 test: test-dump test-verify 
     13test: test-dump test-verify test-verify-armoured test-create-key 
    1414 
    1515lib: 
     
    3030create-signed-key: create-signed-key.o $(LIBDEPS) 
    3131        $(CC) $(LDFLAGS) -o create-signed-key create-signed-key.o $(LIBS) 
     32 
     33sign-detached: sign-detached.o $(LIBDEPS) 
     34        $(CC) $(LDFLAGS) -o sign-detached sign-detached.o $(LIBS) 
    3235 
    3336tags: 
     
    5154# tests 
    5255 
     56SCRATCH=../scratch 
     57 
     58$(SCRATCH): 
     59        mkdir $(SCRATCH) 
     60 
    5361test-dump: packet-dump 
    5462        ./packet-dump < ../test/dsa-public-key-2118CF83.raw 
     
    6573        ./verify2 -a ../test/rsa-public-key-2719AF35.raw ../test/clearsign.txt 
    6674 
     75test-create-key: $(SCRATCH) 
     76        ./create-signed-key "A Test Key" $(SCRATCH)/key.sec $(SCRATCH)/key.pub 
     77 
    6778include .depend 
  • openpgpsdk/trunk/examples/common.c

    r297 r304  
    1919    } 
    2020     
    21 ops_secret_key_t *get_key(const char *keyfile) 
     21ops_secret_key_t *get_secret_key(const char *keyfile) 
    2222    { 
    2323    ops_reader_fd_arg_t arg; 
  • openpgpsdk/trunk/examples/common.h

    r297 r304  
    11#include <openpgpsdk/packet-parse.h> 
    22 
    3 ops_secret_key_t *get_key(const char *keyfile); 
     3ops_secret_key_t *get_secret_key(const char *keyfile); 
  • openpgpsdk/trunk/examples/create-signed-key.c

    r301 r304  
    44#include <openpgpsdk/signature.h> 
    55#include <openpgpsdk/packet-parse.h> 
     6#include <openssl/rsa.h> 
    67#include <stdio.h> 
    78#include <fcntl.h> 
    89#include <string.h> 
    9 #include <assert.h> 
     10#include <unistd.h> 
     11 
     12// XXX: rename to create-self-signed-key 
    1013 
    1114/* 
     
    2326    unsigned char keyid[OPS_KEY_ID_SIZE]; 
    2427    unsigned char *user_id; /* not const coz we use _fast_ */ 
    25     const char *keyfile; 
    26     ops_secret_key_t *skey; 
     28    ops_secret_key_t skey; 
     29    RSA *rsa; 
     30    const char *secfile; 
     31    const char *pubfile; 
     32    BIGNUM *f4; 
    2733 
    28  
    29     if(argc != 3) 
     34    if(argc != 4) 
    3035        { 
    31         fprintf(stderr,"%s <secret key file> <user_id>\n",argv[0]); 
     36        fprintf(stderr,"%s <user_id> <secret key file> <public key file>\n", 
     37                argv[0]); 
    3238        exit(1); 
    3339        } 
    3440 
    35     keyfile=argv[1]; 
    36     user_id=(unsigned char *)argv[2]; 
     41    user_id=argv[1]; 
     42    secfile=argv[2]; 
     43    pubfile=argv[3]; 
     44 
     45    f4=BN_new(); 
     46    BN_set_word(f4,RSA_F4); 
     47 
     48    rsa=RSA_new(); 
     49    RSA_generate_key_ex(rsa,1024,f4,NULL); 
    3750 
    3851    ops_init(); 
    3952 
    40     skey=get_key(keyfile); 
    41     assert(skey); 
     53    // OpenSSL has p and q reversed relative to OpenPGP 
     54    ops_fast_create_rsa_secret_key(&skey,time(NULL),rsa->q,rsa->p,rsa->d, 
     55                                   rsa->iqmp,rsa->n,rsa->e); 
    4256 
    43     arg.fd=1; 
     57    skey.key.rsa.p=rsa->q; 
     58    skey.key.rsa.q=rsa->p; 
     59    skey.key.rsa.d=rsa->d; 
     60    skey.key.rsa.u=rsa->iqmp; 
     61 
     62    arg.fd=open(secfile,O_CREAT|O_TRUNC|O_WRONLY,0666); 
     63    if(arg.fd < 0) 
     64        { 
     65        perror(secfile); 
     66        exit(2); 
     67        } 
     68 
    4469    info.writer=ops_writer_fd; 
    4570    info.arg=&arg; 
    4671 
    47     ops_write_struct_public_key(&skey->public_key,&info); 
     72    ops_write_struct_secret_key(&skey,&info); 
     73 
     74    close(arg.fd); 
     75 
     76    arg.fd=open(pubfile,O_CREAT|O_TRUNC|O_WRONLY,0666); 
     77    if(arg.fd < 0) 
     78        { 
     79        perror(pubfile); 
     80        exit(2); 
     81        } 
     82 
     83    ops_write_struct_public_key(&skey.public_key,&info); 
    4884 
    4985    ops_fast_create_user_id(&id,user_id); 
    5086    ops_write_struct_user_id(&id,&info); 
    5187 
    52     ops_signature_start(&sig,&skey->public_key,&id,OPS_CERT_POSITIVE); 
     88    ops_signature_start_key_signature(&sig,&skey.public_key,&id, 
     89                                      OPS_CERT_POSITIVE); 
    5390    ops_signature_add_creation_time(&sig,time(NULL)); 
    5491 
    55     ops_keyid(keyid,&skey->public_key); 
     92    ops_keyid(keyid,&skey.public_key); 
    5693    ops_signature_add_issuer_key_id(&sig,keyid); 
    5794 
     
    6097    ops_signature_hashed_subpackets_end(&sig); 
    6198 
    62     ops_write_signature(&sig,&skey->public_key,skey,&info); 
    63  
    64     ops_secret_key_free(skey); 
     99    ops_write_signature(&sig,&skey.public_key,&skey,&info); 
    65100 
    66101    ops_finish(); 
    67102 
     103    close(arg.fd); 
     104 
    68105    return 0; 
    69106    } 
  • openpgpsdk/trunk/include/openpgpsdk/create.h

    r302 r304  
    4646typedef struct ops_create_info ops_create_info_t; 
    4747 
    48  
    49 /** \ingroup Create 
    50  * needed for signature creation 
    51  */ 
    52 typedef struct 
    53     { 
    54     ops_packet_writer_t *writer; /*!< The writer function */ 
    55     void *arg;  /*!< Arguments for the writer function */ 
    56     ops_hash_t hash;  
    57     ops_signature_t sig;  
    58     ops_memory_t mem;  
    59     ops_create_info_t info; /*!< how to do the writing */ 
    60     unsigned hashed_count_offset; 
    61     unsigned hashed_data_length; 
    62     unsigned unhashed_count_offset; 
    63     } ops_create_signature_t; 
    64  
    6548ops_boolean_t ops_write(const void *src,unsigned length, 
    6649                        ops_create_info_t *opt); 
     
    9073ops_boolean_t ops_write_user_id(const unsigned char *user_id,ops_create_info_t *opt); 
    9174 
     75void ops_create_rsa_secret_key(ops_secret_key_t *key,const BIGNUM *p, 
     76                               const BIGNUM *q,const BIGNUM *d, 
     77                               const BIGNUM *u,const BIGNUM *n, 
     78                               const BIGNUM *e); 
     79void ops_fast_create_rsa_secret_key(ops_secret_key_t *key,time_t time, 
     80                                    BIGNUM *p,BIGNUM *q,BIGNUM *d,BIGNUM *u, 
     81                                    BIGNUM *n,BIGNUM *e); 
     82ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key, 
     83                                          ops_create_info_t *info); 
     84 
    9285#endif 
  • openpgpsdk/trunk/include/openpgpsdk/crypto.h

    r279 r304  
    99 
    1010#define OPS_MAX_HASH    64 
    11  
    12 /** ops_hash_t */ 
    13 typedef struct _ops_hash_t ops_hash_t; 
    1411 
    1512typedef void ops_hash_init_t(ops_hash_t *hash); 
  • openpgpsdk/trunk/include/openpgpsdk/signature.h

    r301 r304  
    55#include "util.h" 
    66#include "create.h" 
     7 
     8/** \ingroup Create 
     9 * needed for signature creation 
     10 */ 
     11typedef struct 
     12    { 
     13    ops_packet_writer_t *writer; /*!< The writer function */ 
     14    void *arg;  /*!< Arguments for the writer function */ 
     15    ops_hash_t hash;  
     16    ops_signature_t sig;  
     17    ops_memory_t mem;  
     18    ops_create_info_t info; /*!< how to do the writing */ 
     19    unsigned hashed_count_offset; 
     20    unsigned hashed_data_length; 
     21    unsigned unhashed_count_offset; 
     22    } ops_create_signature_t; 
    723 
    824ops_boolean_t 
     
    2238                         const ops_signature_t *sig, 
    2339                         const ops_public_key_t *signer); 
    24 void ops_signature_start(ops_create_signature_t *sig, 
    25                          const ops_public_key_t *key, 
    26                          const ops_user_id_t *id,ops_sig_type_t type); 
     40void ops_signature_start_key_signature(ops_create_signature_t *sig, 
     41                                       const ops_public_key_t *key, 
     42                                       const ops_user_id_t *id, 
     43                                       ops_sig_type_t type); 
     44void ops_signature_start_plaintext_signature(ops_create_signature_t *sig, 
     45                                             ops_hash_algorithm_t hash, 
     46                                             ops_sig_type_t type); 
     47void ops_signature_add_data(ops_create_signature_t *sig,const void *buf, 
     48                            size_t length); 
    2749void ops_signature_hashed_subpackets_end(ops_create_signature_t *sig); 
    2850void ops_write_signature(ops_create_signature_t *sig,ops_public_key_t *key, 
     
    3355void ops_signature_add_primary_user_id(ops_create_signature_t *sig, 
    3456                                       ops_boolean_t primary); 
    35  
  • openpgpsdk/trunk/include/openpgpsdk/types.h

    r280 r304  
    2424/** ops_content_tag_t */ 
    2525typedef enum ops_content_tag_t ops_content_tag_t; 
     26 
     27/** ops_hash_t */ 
     28typedef struct _ops_hash_t ops_hash_t; 
    2629 
    2730/**  
  • openpgpsdk/trunk/src/create.c

    r302 r304  
    88 
    99/* 
    10  * return 1 if OK, otherwise 0 
    11  */ 
    12 static int base_write(const void *src,unsigned length, 
    13                        ops_create_info_t *info) 
    14     { 
    15     return info->writer(src,length,0,info->arg) == OPS_W_OK; 
     10 * return true if OK, otherwise false 
     11 */ 
     12static ops_boolean_t base_write(const void *src,unsigned length, 
     13                               ops_create_info_t *info) 
     14    { 
     15    return info->writer(src,length,0,info) == OPS_W_OK; 
    1616    } 
    1717 
     
    202202    /* not reached */ 
    203203    return 0; 
     204    } 
     205 
     206static unsigned secret_key_length(const ops_secret_key_t *key) 
     207    { 
     208    int l; 
     209 
     210    switch(key->public_key.algorithm) 
     211        { 
     212    case OPS_PKA_RSA: 
     213        l=mpi_length(key->key.rsa.d)+mpi_length(key->key.rsa.p) 
     214            +mpi_length(key->key.rsa.q)+mpi_length(key->key.rsa.u); 
     215        break; 
     216 
     217    default: 
     218        assert(!"unknown key algorithm"); 
     219        } 
     220 
     221    return l+public_key_length(&key->public_key); 
    204222    } 
    205223 
     
    223241/* Note that we support v3 keys here because they're needed for 
    224242 * for verification - the writer doesn't allow them, though */ 
    225 static int write_public_key_body(const ops_public_key_t *key, 
    226                                   ops_create_info_t *info) 
     243static ops_boolean_t write_public_key_body(const ops_public_key_t *key, 
     244                                          ops_create_info_t *info) 
    227245    { 
    228246    if(!(ops_write_scalar(key->version,1,info) 
     
    264282    } 
    265283 
     284static void push_secret_key_checksum_writer(ops_create_info_t *info) 
     285    { 
     286    OPS_USED(info); 
     287    // XXX: push a SHA-1 checksum writer (and change s2k to 254). 
     288    } 
     289 
     290static ops_boolean_t pop_secret_key_checksum_writer(ops_create_info_t *info) 
     291    { 
     292    // XXX: actually write a SHA-1 checksum, but for now, dummy... 
     293    return ops_write_scalar(0,2,info); 
     294    } 
     295 
     296 
     297/* Note that we support v3 keys here because they're needed for 
     298 * for verification - the writer doesn't allow them, though */ 
     299static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key, 
     300                                           ops_create_info_t *info) 
     301    { 
     302    if(!write_public_key_body(&key->public_key,info)) 
     303        return ops_false; 
     304 
     305    if(!ops_write_scalar(key->s2k_usage,1,info)) 
     306        return ops_false; 
     307     
     308    // XXX: for now, no secret key encryption, so s2k == 0 
     309    assert(key->s2k_usage == OPS_S2K_NONE); 
     310 
     311    push_secret_key_checksum_writer(info); 
     312 
     313    switch(key->public_key.algorithm) 
     314        { 
     315        //    case OPS_PKA_DSA: 
     316        //      return ops_write_mpi(key->key.dsa.x,info); 
     317 
     318    case OPS_PKA_RSA: 
     319    case OPS_PKA_RSA_ENCRYPT_ONLY: 
     320    case OPS_PKA_RSA_SIGN_ONLY: 
     321        if(!ops_write_mpi(key->key.rsa.d,info) 
     322           || !ops_write_mpi(key->key.rsa.p,info) 
     323           || !ops_write_mpi(key->key.rsa.q,info) 
     324           || !ops_write_mpi(key->key.rsa.u,info)) 
     325            return ops_false; 
     326        break; 
     327 
     328        //    case OPS_PKA_ELGAMAL: 
     329        //      return ops_write_mpi(key->key.elgamal.x,info); 
     330 
     331    default: 
     332        assert(0); 
     333        break; 
     334        } 
     335 
     336    return pop_secret_key_checksum_writer(info); 
     337    } 
     338 
     339 
    266340/** 
    267341 * \ingroup Create 
     
    338412        ops_memory_make_packet(out,OPS_PTAG_CT_PUBLIC_KEY); 
    339413    } 
     414 
     415/** 
     416 * \ingroup Create 
     417 * 
     418 * Create an RSA secret key structure. If a parameter is marked as 
     419 * [OPTIONAL], then it can be omitted and will be calculated from 
     420 * other parameters - or, in the case of e, will default to 0x10001. 
     421 * 
     422 * Parameters are _not_ copied, so will be freed if the structure is 
     423 * freed. 
     424 * 
     425 * \param key The key structure to be initialised. 
     426 * \param e The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL] 
     427 * \param p The RSA parameter p 
     428 * \param q The RSA parameter q (q > p) 
     429 * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL] 
     430 * \param n The RSA public parameter n (=p*q) [OPTIONAL] 
     431 * \param e The RSA public parameter e */ 
     432 
     433void ops_fast_create_rsa_secret_key(ops_secret_key_t *key,time_t time, 
     434                                    BIGNUM *d,BIGNUM *p,BIGNUM *q,BIGNUM *u, 
     435                                    BIGNUM *n,BIGNUM *e) 
     436    { 
     437    ops_fast_create_rsa_public_key(&key->public_key,time,n,e); 
     438 
     439    // XXX: calculate optionals 
     440    key->key.rsa.d=d; 
     441    key->key.rsa.p=p; 
     442    key->key.rsa.q=q; 
     443    key->key.rsa.u=u; 
     444 
     445    key->s2k_usage=OPS_S2K_NONE; 
     446 
     447    // XXX: sanity check and add errors... 
     448    } 
     449 
     450/** 
     451 * \ingroup Create 
     452 * 
     453 * Writes a secret key. 
     454 * 
     455 * \param key The secret key 
     456 * \param info 
     457 * \return success 
     458 */ 
     459ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key, 
     460                                          ops_create_info_t *info) 
     461    { 
     462    assert(key->public_key.version == 4); 
     463 
     464    return ops_write_ptag(OPS_PTAG_CT_SECRET_KEY,info) 
     465        && ops_write_length(1+4+1+1+secret_key_length(key)+2,info) 
     466        && write_secret_key_body(key,info); 
     467    } 
  • openpgpsdk/trunk/src/packet-parse.c

    r299 r304  
    16831683        return 0; 
    16841684    C.secret_key.s2k_usage=c[0]; 
    1685     assert(C.secret_key.s2k_usage == 0); 
     1685    assert(C.secret_key.s2k_usage == OPS_S2K_NONE); 
    16861686 
    16871687    switch(C.secret_key.public_key.algorithm) 
  • openpgpsdk/trunk/src/signature.c

    r301 r304  
    127127    } 
    128128 
     129static void common_init_signature(ops_hash_t *hash,const ops_signature_t *sig) 
     130    { 
     131    ops_hash_any(hash,sig->hash_algorithm); 
     132    hash->init(hash); 
     133    } 
     134 
    129135static void init_signature(ops_hash_t *hash,const ops_signature_t *sig, 
    130136                           const ops_public_key_t *key) 
    131137    { 
    132     ops_hash_any(hash,sig->hash_algorithm); 
    133     hash->init(hash); 
     138    common_init_signature(hash,sig); 
    134139    hash_add_key(hash,key); 
    135140    } 
     
    290295 * \ingroup Create 
    291296 * 
    292  * ops_signature_start() creates a V4 signature with a SHA1 hash. 
     297 * ops_signature_start() creates a V4 public key signature with a SHA1 hash. 
    293298 *  
    294  * \param sig 
    295  * \param key 
    296  * \param id 
    297  * \param type 
    298  * \todo Expand description. 
    299  */ 
    300 void ops_signature_start(ops_create_signature_t *sig, 
    301                          const ops_public_key_t *key, 
    302                          const ops_user_id_t *id, 
    303                          ops_sig_type_t type) 
    304     { 
     299 * \param sig The signature structure to initialise 
     300 * \param key The public key to be signed 
     301 * \param id The user ID being bound to the key 
     302 * \param type Signature type 
     303 * \todo Expand description. Allow other hashes. 
     304 */ 
     305void ops_signature_start_key_signature(ops_create_signature_t *sig, 
     306                                       const ops_public_key_t *key, 
     307                                       const ops_user_id_t *id, 
     308                                       ops_sig_type_t type) 
     309    { 
     310    memset(sig,'\0',sizeof *sig); 
    305311    // XXX: refactor with check (in several ways - check should probably 
    306312    // use the buffered writer to construct packets (done), and also should 
     
    315321    init_signature(&sig->hash,&sig->sig,key); 
    316322 
    317     // \todo Fix this. user_id is UTF-8 so strlen may not work 
    318323    ops_hash_add_int(&sig->hash,0xb4,1); 
    319324    ops_hash_add_int(&sig->hash,strlen((char *)id->user_id),4); 
     
    335340    sig->hashed_count_offset=sig->mem.length; 
    336341    ops_write_scalar(0,2,&sig->info); 
     342    } 
     343 
     344/** 
     345 * \ingroup Create 
     346 * 
     347 * Create a V4 public key signature over some plaintext. 
     348 *  
     349 * \param sig The signature structure to initialise 
     350 * \param id 
     351 * \param type 
     352 * \todo Expand description. Allow other hashes. 
     353 */ 
     354void ops_signature_start_plaintext_signature(ops_create_signature_t *sig, 
     355                                             ops_hash_algorithm_t hash, 
     356                                             ops_sig_type_t type) 
     357    { 
     358    memset(sig,'\0',sizeof *sig); 
     359    // XXX: refactor with check (in several ways - check should probably 
     360    // use the buffered writer to construct packets (done), and also should 
     361    // share code for hash calculation) 
     362    sig->sig.version=OPS_SIG_V4; 
     363    sig->sig.hash_algorithm=hash; 
     364    sig->sig.type=type; 
     365 
     366    sig->hashed_data_length=-1; 
     367 
     368    common_init_signature(&sig->hash,&sig->sig); 
     369 
     370    // since this has subpackets and stuff, we have to buffer the whole 
     371    // thing to get counts before writing. 
     372    ops_memory_init(&sig->mem,100); 
     373    sig->info.writer=ops_writer_memory; 
     374    sig->info.arg=&sig->mem; 
     375 
     376    // write nearly up to the first subpacket 
     377    ops_write_scalar(sig->sig.version,1,&sig->info); 
     378    ops_write_scalar(sig->sig.type,1,&sig->info); 
     379    ops_write_scalar(sig->sig.key_algorithm,1,&sig->info); 
     380    ops_write_scalar(sig->sig.hash_algorithm,1,&sig->info); 
     381 
     382    // dummy hashed subpacket count 
     383    sig->hashed_count_offset=sig->mem.length; 
     384    ops_write_scalar(0,2,&sig->info); 
     385    } 
     386 
     387/** 
     388 * \ingroup Create 
     389 * 
     390 * Add plaintext data to a signature-to-be. 
     391 * 
     392 * \param sig The signature-to-be. 
     393 * \param buf The plaintext data. 
     394 * \param length The amount of plaintext data. 
     395 */ 
     396void ops_signature_add_data(ops_create_signature_t *sig,const void *buf, 
     397                            size_t length) 
     398    { 
     399    sig->hash.add(&sig->hash,buf,length); 
    337400    } 
    338401