#include <stdio.h>
#include <string.h>
#include <time.h>
#include <bn.h>
#include <rsa.h>
#include <idea.h>
#include <rand.h>

/*------------------------------------------------------------------------*/
void keyout2(FILE * secout, FILE * pubout, unsigned char *hashpass,
             char *userid, RSA * newkey)
{
  unsigned char dbuf[2048], *bp;
  unsigned long i, ll, len, cks, j, k;
  unsigned char ideavec[8];
  IDEA_KEY_SCHEDULE iksch;
  int ivcnt;
  BIGNUM *bnptr;

  memset(dbuf, 0, 11);
  dbuf[0] = 0x95;
  i = time(NULL);               /* timestamp */
  bp = &dbuf[3];
  *bp++ = 3;
  *bp++ = i >> 24, *bp++ = i >> 16, *bp++ = i >> 8, *bp++ = i;
  dbuf[10] = 1;
  len = 8;
  if (secout)
    fwrite(dbuf, 1, 11, secout);
  dbuf[0] = 0x99;
  fwrite(dbuf, 1, 11, pubout);
  bnptr = newkey->n;
  for (j = 0; j < 2; j++) {
    i = BN_num_bits(bnptr);
    dbuf[0] = i >> 8, dbuf[1] = i;
    BN_bn2bin(bnptr, &dbuf[2]);
    ll = 2 + (i + 7) / 8;
    if (secout)
      fwrite(dbuf, 1, ll, secout);
    fwrite(dbuf, 1, ll, pubout);
    len += ll;
    bnptr = newkey->e;
  }
  /* mark as axiomatic */
  fputc(0xb0, pubout), fputc(0x01, pubout), fputc(0x87, pubout);

  fputc(0xb4, pubout);
  fputc(strlen(userid), pubout);
  fwrite(userid, 1, strlen(userid), pubout);

  fseek(pubout, 1, SEEK_SET);
  fputc(len >> 8, pubout), fputc(len, pubout);
  if (!secout)
    return;
  fputc(hashpass != NULL, secout);
  len++;
  if (hashpass) {
    RAND_bytes(ideavec, 8);
    fwrite(ideavec, 1, 8, secout);
    len += 8;
    idea_set_encrypt_key(hashpass, &iksch);
    ivcnt = 0;
  }
  cks = 0;
  bnptr = newkey->d;
  for (k = 0; k < 4; k++) {
    i = BN_num_bits(bnptr);
    dbuf[0] = i >> 8, dbuf[1] = i;
    BN_bn2bin(bnptr, &dbuf[2]);
    ll = 2 + (i + 7) / 8;
    for (j = 0; j < ll; j++)
      cks += dbuf[j];
    if (hashpass)
      idea_cfb64_encrypt(&dbuf[2], &dbuf[2], ll - 2, &iksch,
                         ideavec, &ivcnt, IDEA_ENCRYPT);
    fwrite(dbuf, 1, ll, secout);
    len += ll;
    if (k == 0)
      bnptr = newkey->q;
    else if (k == 1)
      bnptr = newkey->p;
    else if (k == 2)
      bnptr = newkey->iqmp;
  }
  fputc(cks >> 8, secout), fputc(cks, secout);  /* checksum */
  len += 2;
  fputc(0xb4, secout);
  fputc(strlen(userid), secout);
  fwrite(userid, 1, strlen(userid), secout);
  fseek(secout, 1, SEEK_SET);
  fputc(len >> 8, secout), fputc(len, secout);
}
