blob: 2721dee7e625d151ce9140a6eac870441dd81b03 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Jeff Thompsonc0573432013-09-19 17:41:36 -07002/**
Yingdi Yu99b2a002015-08-12 12:47:44 -07003 * Copyright (c) 2013-2016 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
22 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Jeff Thompsonc0573432013-09-19 17:41:36 -070023 */
24
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080025#include "public-key.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070026
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070027#include "../../encoding/oid.hpp"
28#include "../../util/crypto.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070029#include "cryptopp.hpp"
Jeff Thompsonc0573432013-09-19 17:41:36 -070030
Jeff Thompsonc0573432013-09-19 17:41:36 -070031namespace ndn {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070032namespace security {
33namespace v1 {
Jeff Thompsonc0573432013-09-19 17:41:36 -070034
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080035PublicKey::PublicKey()
Yingdi Yu99b2a002015-08-12 12:47:44 -070036 : m_type(KeyType::NONE)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080037{
Jeff Thompsonc0573432013-09-19 17:41:36 -070038}
Jeff Thompsonc0573432013-09-19 17:41:36 -070039
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070040PublicKey::PublicKey(const uint8_t* keyDerBuf, size_t keyDerSize)
Yingdi Yu99b2a002015-08-12 12:47:44 -070041 : m_type(KeyType::NONE)
Jeff Thompsonc0573432013-09-19 17:41:36 -070042{
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070043 CryptoPP::StringSource src(keyDerBuf, keyDerSize, true);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080044 decode(src);
Jeff Thompsonc0573432013-09-19 17:41:36 -070045}
46
Yingdi Yue36322a2014-11-04 14:16:54 -080047const Block&
48PublicKey::computeDigest() const
49{
50 if (m_key.empty())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070051 BOOST_THROW_EXCEPTION(Error("Public key is empty"));
Yingdi Yue36322a2014-11-04 14:16:54 -080052
53 if (m_digest.hasWire())
54 return m_digest;
55 else {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070056 m_digest = Block(tlv::KeyDigest, crypto::computeSha256Digest(m_key.buf(), m_key.size()));
Yingdi Yue36322a2014-11-04 14:16:54 -080057 m_digest.encode();
58 return m_digest;
59 }
60}
61
62
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080063void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070064PublicKey::encode(CryptoPP::BufferedTransformation& out) const
Jeff Thompsonc0573432013-09-19 17:41:36 -070065{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080066 // SubjectPublicKeyInfo ::= SEQUENCE {
67 // algorithm AlgorithmIdentifier
68 // keybits BIT STRING }
69
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070070 out.Put(m_key.buf(), m_key.size());
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080071}
72
73void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070074PublicKey::decode(CryptoPP::BufferedTransformation& in)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080075{
76 // SubjectPublicKeyInfo ::= SEQUENCE {
77 // algorithm AlgorithmIdentifier
78 // keybits BIT STRING }
79
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070080 using namespace CryptoPP;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070081 try
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080082 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070083 std::string out;
84 StringSink sink(out);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080085
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070086 ////////////////////////
87 // part 1: copy as is //
88 ////////////////////////
89 BERSequenceDecoder decoder(in);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080090 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070091 assert(decoder.IsDefiniteLength());
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080092
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070093 DERSequenceEncoder encoder(sink);
94 decoder.TransferTo(encoder, decoder.RemainingLength());
95 encoder.MessageEnd();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080096 }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070097 decoder.MessageEnd();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080098
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070099 ////////////////////////
100 // part 2: check if the key is RSA (since it is the only supported for now)
101 ////////////////////////
102 StringSource checkedSource(out, true);
103 BERSequenceDecoder subjectPublicKeyInfo(checkedSource);
104 {
105 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
106 {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700107 Oid algorithm;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700108 algorithm.decode(algorithmInfo);
109
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700110 if (algorithm == oid::RSA)
Yingdi Yu99b2a002015-08-12 12:47:44 -0700111 m_type = KeyType::RSA;
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700112 else if (algorithm == oid::ECDSA)
Yingdi Yu99b2a002015-08-12 12:47:44 -0700113 m_type = KeyType::EC;
Yingdi Yu2620b1c2014-06-12 15:32:57 -0700114 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700115 BOOST_THROW_EXCEPTION(Error("Only RSA/ECDSA public keys are supported for now (" +
116 algorithm.toString() + " requested)"));
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700117 }
118 }
119
120 m_key.assign(out.begin(), out.end());
121 }
122 catch (CryptoPP::BERDecodeErr& err)
123 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700124 m_type = KeyType::NONE;
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700125 BOOST_THROW_EXCEPTION(Error("PublicKey decoding error"));
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700126 }
Yingdi Yue36322a2014-11-04 14:16:54 -0800127
128 m_digest.reset();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800129}
130
131// Blob
132// PublicKey::getDigest(DigestAlgorithm digestAlgorithm) const
133// {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700134// if (digestAlgorithm == DigestAlgorithm::SHA256) {
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800135// uint8_t digest[SHA256_DIGEST_LENGTH];
136// ndn_digestSha256(keyDer_.buf(), keyDer_.size(), digest);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700137
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800138// return Blob(digest, sizeof(digest));
139// }
140// else
141// throw UnrecognizedDigestAlgorithmException("Wrong format!");
142// }
143
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700144std::ostream&
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700145operator<<(std::ostream& os, const PublicKey& key)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800146{
147 CryptoPP::StringSource(key.get().buf(), key.get().size(), true,
148 new CryptoPP::Base64Encoder(new CryptoPP::FileSink(os), true, 64));
149
150 return os;
Jeff Thompsonc0573432013-09-19 17:41:36 -0700151}
152
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700153} // namespace v1
154} // namespace security
Yingdi Yufc40d872014-02-18 12:56:04 -0800155} // namespace ndn