示例#1
0
void
FilePrivateKeyStorage::generateKeyPair
  (const Name& keyName, const KeyParams& params)
{
  if (doesKeyExist(keyName, KEY_CLASS_PUBLIC))
    throw SecurityException("Public Key already exists");
  if (doesKeyExist(keyName, KEY_CLASS_PRIVATE))
    throw SecurityException("Private Key already exists");

  Blob publicKeyDer;
  Blob privateKeyDer;

  if (params.getKeyType() == KEY_TYPE_RSA) {
    const RsaKeyParams& rsaParams = static_cast<const RsaKeyParams&>(params);

    BIGNUM* exponent = 0;
    RSA* rsa = 0;

    exponent = BN_new();
    if (BN_set_word(exponent, RSA_F4) == 1) {
      rsa = RSA_new();
      if (RSA_generate_key_ex(rsa, rsaParams.getKeySize(), exponent, NULL) == 1) {
        // Encode the public key.
        int length = i2d_RSA_PUBKEY(rsa, NULL);
        publicKeyDer = Blob(ptr_lib::make_shared<vector<uint8_t> >(length), false);
        uint8_t* derPointer = const_cast<uint8_t*>(publicKeyDer.buf());
        i2d_RSA_PUBKEY(rsa, &derPointer);

        // Encode the private key.
        length = i2d_RSAPrivateKey(rsa, NULL);
        vector<uint8_t> pkcs1PrivateKeyDer(length);
        derPointer = &pkcs1PrivateKeyDer[0];
        i2d_RSAPrivateKey(rsa, &derPointer);
        privateKeyDer = encodePkcs8PrivateKey
          (pkcs1PrivateKeyDer, OID(RSA_ENCRYPTION_OID),
           ptr_lib::make_shared<DerNode::DerNull>());
      }
    }

    BN_free(exponent);
    RSA_free(rsa);
  }
  else if (params.getKeyType() == KEY_TYPE_ECDSA) {
    const EcdsaKeyParams& ecdsaParams = static_cast<const EcdsaKeyParams&>(params);

    OID parametersOid;
    int curveId = -1;

    // Find the entry in EC_KEY_INFO.
    for (size_t i = 0 ; i < sizeof(EC_KEY_INFO) / sizeof(EC_KEY_INFO[0]); ++i) {
      if (EC_KEY_INFO[i].keySize == ecdsaParams.getKeySize()) {
        curveId = EC_KEY_INFO[i].curveId;
        parametersOid.setIntegerList
          (EC_KEY_INFO[i].oidIntegerList, EC_KEY_INFO[i].oidIntegerListLength);

        break;
      }
    }
    if (curveId == -1)
      throw SecurityException("Unsupported keySize for KEY_TYPE_ECDSA");

    EC_KEY* ecKey = EC_KEY_new_by_curve_name(curveId);
    if (ecKey != NULL) {
      if (EC_KEY_generate_key(ecKey) == 1) {
        // Encode the public key.
        int length = i2d_EC_PUBKEY(ecKey, NULL);
        vector<uint8_t> opensslPublicKeyDer(length);
        uint8_t* derPointer = &opensslPublicKeyDer[0];
        i2d_EC_PUBKEY(ecKey, &derPointer);
        // Convert the openssl style to ndn-cxx which has the simple AlgorithmIdentifier.
        // Find the bit string which is the second child.
        ptr_lib::shared_ptr<DerNode> parsedNode = DerNode::parse
          (&opensslPublicKeyDer[0], 0);
        const std::vector<ptr_lib::shared_ptr<DerNode> >& children =
          parsedNode->getChildren();
        publicKeyDer = encodeSubjectPublicKeyInfo
          (OID(EC_ENCRYPTION_OID),
           ptr_lib::make_shared<DerNode::DerOid>(parametersOid), children[1]);

        // Encode the private key.
        EC_KEY_set_enc_flags(ecKey, EC_PKEY_NO_PARAMETERS | EC_PKEY_NO_PUBKEY);
        length = i2d_ECPrivateKey(ecKey, NULL);
        vector<uint8_t> pkcs1PrivateKeyDer(length);
        derPointer = &pkcs1PrivateKeyDer[0];
        i2d_ECPrivateKey(ecKey, &derPointer);
        privateKeyDer = encodePkcs8PrivateKey
          (pkcs1PrivateKeyDer, OID(EC_ENCRYPTION_OID),
           ptr_lib::make_shared<DerNode::DerOid>(parametersOid));
      }
    }

    EC_KEY_free(ecKey);
  }
  else
    throw SecurityException("Unsupported key type");

  string keyUri = keyName.toUri();
  string publicKeyFilePath = nameTransform(keyUri, ".pub");
  string privateKeyFilePath = nameTransform(keyUri, ".pri");

  ofstream publicKeyFile(publicKeyFilePath.c_str());
  publicKeyFile << toBase64(publicKeyDer.buf(), publicKeyDer.size(), true);
  ofstream privateKeyFile(privateKeyFilePath.c_str());
  privateKeyFile << toBase64(privateKeyDer.buf(), privateKeyDer.size(), true);

  ::chmod(publicKeyFilePath.c_str(),  S_IRUSR | S_IRGRP | S_IROTH);
  ::chmod(privateKeyFilePath.c_str(), S_IRUSR);
}