blob: bed8f810c2f3dc23d3634acd985941d3fe02abe7 [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 -080032static OID RSA_OID("1.2.840.113549.1.1.1");
Yingdi Yu2620b1c2014-06-12 15:32:57 -070033static OID ECDSA_OID("1.2.840.10045.2.1");
Jeff Thompsonc0573432013-09-19 17:41:36 -070034
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080035PublicKey::PublicKey()
Yingdi Yu2620b1c2014-06-12 15:32:57 -070036 : m_type(KEY_TYPE_NULL)
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 Yu2620b1c2014-06-12 15:32:57 -070041 : m_type(KEY_TYPE_NULL)
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
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080047void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070048PublicKey::encode(CryptoPP::BufferedTransformation& out) const
Jeff Thompsonc0573432013-09-19 17:41:36 -070049{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080050 // SubjectPublicKeyInfo ::= SEQUENCE {
51 // algorithm AlgorithmIdentifier
52 // keybits BIT STRING }
53
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070054 out.Put(m_key.buf(), m_key.size());
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080055}
56
57void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070058PublicKey::decode(CryptoPP::BufferedTransformation& in)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080059{
60 // SubjectPublicKeyInfo ::= SEQUENCE {
61 // algorithm AlgorithmIdentifier
62 // keybits BIT STRING }
63
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070064 using namespace CryptoPP;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070065 try
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080066 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070067 std::string out;
68 StringSink sink(out);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080069
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070070 ////////////////////////
71 // part 1: copy as is //
72 ////////////////////////
73 BERSequenceDecoder decoder(in);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080074 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070075 assert(decoder.IsDefiniteLength());
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080076
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070077 DERSequenceEncoder encoder(sink);
78 decoder.TransferTo(encoder, decoder.RemainingLength());
79 encoder.MessageEnd();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080080 }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070081 decoder.MessageEnd();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080082
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070083 ////////////////////////
84 // part 2: check if the key is RSA (since it is the only supported for now)
85 ////////////////////////
86 StringSource checkedSource(out, true);
87 BERSequenceDecoder subjectPublicKeyInfo(checkedSource);
88 {
89 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
90 {
91 OID algorithm;
92 algorithm.decode(algorithmInfo);
93
Yingdi Yu2620b1c2014-06-12 15:32:57 -070094 if (algorithm == RSA_OID)
95 m_type = KEY_TYPE_RSA;
96 else if (algorithm == ECDSA_OID)
97 m_type = KEY_TYPE_ECDSA;
98 else
99 throw Error("Only RSA/ECDSA public keys are supported for now (" +
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700100 algorithm.toString() + " requested)");
101 }
102 }
103
104 m_key.assign(out.begin(), out.end());
105 }
106 catch (CryptoPP::BERDecodeErr& err)
107 {
Yingdi Yu2620b1c2014-06-12 15:32:57 -0700108 m_type = KEY_TYPE_NULL;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700109 throw Error("PublicKey decoding error");
110 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800111}
112
113// Blob
114// PublicKey::getDigest(DigestAlgorithm digestAlgorithm) const
115// {
116// if (digestAlgorithm == DIGEST_ALGORITHM_SHA256) {
117// uint8_t digest[SHA256_DIGEST_LENGTH];
118// ndn_digestSha256(keyDer_.buf(), keyDer_.size(), digest);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700119
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800120// return Blob(digest, sizeof(digest));
121// }
122// else
123// throw UnrecognizedDigestAlgorithmException("Wrong format!");
124// }
125
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700126std::ostream&
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700127operator<<(std::ostream& os, const PublicKey& key)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800128{
129 CryptoPP::StringSource(key.get().buf(), key.get().size(), true,
130 new CryptoPP::Base64Encoder(new CryptoPP::FileSink(os), true, 64));
131
132 return os;
Jeff Thompsonc0573432013-09-19 17:41:36 -0700133}
134
Yingdi Yufc40d872014-02-18 12:56:04 -0800135} // namespace ndn