blob: 801fe6c4a881246025302a036870457639ad5fac [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/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 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
27#include "../encoding/oid.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070028#include "cryptopp.hpp"
Jeff Thompsonc0573432013-09-19 17:41:36 -070029
Jeff Thompsonc0573432013-09-19 17:41:36 -070030namespace ndn {
31
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080032PublicKey::PublicKey()
Yingdi Yu2620b1c2014-06-12 15:32:57 -070033 : m_type(KEY_TYPE_NULL)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080034{
Jeff Thompsonc0573432013-09-19 17:41:36 -070035}
Jeff Thompsonc0573432013-09-19 17:41:36 -070036
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070037PublicKey::PublicKey(const uint8_t* keyDerBuf, size_t keyDerSize)
Yingdi Yu2620b1c2014-06-12 15:32:57 -070038 : m_type(KEY_TYPE_NULL)
Jeff Thompsonc0573432013-09-19 17:41:36 -070039{
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070040 CryptoPP::StringSource src(keyDerBuf, keyDerSize, true);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080041 decode(src);
Jeff Thompsonc0573432013-09-19 17:41:36 -070042}
43
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080044void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070045PublicKey::encode(CryptoPP::BufferedTransformation& out) const
Jeff Thompsonc0573432013-09-19 17:41:36 -070046{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080047 // SubjectPublicKeyInfo ::= SEQUENCE {
48 // algorithm AlgorithmIdentifier
49 // keybits BIT STRING }
50
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070051 out.Put(m_key.buf(), m_key.size());
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080052}
53
54void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070055PublicKey::decode(CryptoPP::BufferedTransformation& in)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080056{
57 // SubjectPublicKeyInfo ::= SEQUENCE {
58 // algorithm AlgorithmIdentifier
59 // keybits BIT STRING }
60
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070061 using namespace CryptoPP;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070062 try
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080063 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070064 std::string out;
65 StringSink sink(out);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080066
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070067 ////////////////////////
68 // part 1: copy as is //
69 ////////////////////////
70 BERSequenceDecoder decoder(in);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080071 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070072 assert(decoder.IsDefiniteLength());
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080073
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070074 DERSequenceEncoder encoder(sink);
75 decoder.TransferTo(encoder, decoder.RemainingLength());
76 encoder.MessageEnd();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080077 }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070078 decoder.MessageEnd();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080079
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070080 ////////////////////////
81 // part 2: check if the key is RSA (since it is the only supported for now)
82 ////////////////////////
83 StringSource checkedSource(out, true);
84 BERSequenceDecoder subjectPublicKeyInfo(checkedSource);
85 {
86 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
87 {
88 OID algorithm;
89 algorithm.decode(algorithmInfo);
90
Yingdi Yu9d9d5992014-06-25 12:25:16 -070091 if (algorithm == oid::RSA)
Yingdi Yu2620b1c2014-06-12 15:32:57 -070092 m_type = KEY_TYPE_RSA;
Yingdi Yu9d9d5992014-06-25 12:25:16 -070093 else if (algorithm == oid::ECDSA)
Yingdi Yu2620b1c2014-06-12 15:32:57 -070094 m_type = KEY_TYPE_ECDSA;
95 else
96 throw Error("Only RSA/ECDSA public keys are supported for now (" +
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070097 algorithm.toString() + " requested)");
98 }
99 }
100
101 m_key.assign(out.begin(), out.end());
102 }
103 catch (CryptoPP::BERDecodeErr& err)
104 {
Yingdi Yu2620b1c2014-06-12 15:32:57 -0700105 m_type = KEY_TYPE_NULL;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700106 throw Error("PublicKey decoding error");
107 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800108}
109
110// Blob
111// PublicKey::getDigest(DigestAlgorithm digestAlgorithm) const
112// {
113// if (digestAlgorithm == DIGEST_ALGORITHM_SHA256) {
114// uint8_t digest[SHA256_DIGEST_LENGTH];
115// ndn_digestSha256(keyDer_.buf(), keyDer_.size(), digest);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700116
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800117// return Blob(digest, sizeof(digest));
118// }
119// else
120// throw UnrecognizedDigestAlgorithmException("Wrong format!");
121// }
122
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700123std::ostream&
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700124operator<<(std::ostream& os, const PublicKey& key)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800125{
126 CryptoPP::StringSource(key.get().buf(), key.get().size(), true,
127 new CryptoPP::Base64Encoder(new CryptoPP::FileSink(os), true, 64));
128
129 return os;
Jeff Thompsonc0573432013-09-19 17:41:36 -0700130}
131
Yingdi Yufc40d872014-02-18 12:56:04 -0800132} // namespace ndn