blob: 212bc3a166c2d3a34e09c3e7390c18e1c8899b04 [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
30using namespace std;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080031using namespace CryptoPP;
Jeff Thompsonc0573432013-09-19 17:41:36 -070032
33namespace ndn {
34
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080035static OID RSA_OID("1.2.840.113549.1.1.1");
Yingdi Yu2620b1c2014-06-12 15:32:57 -070036static OID ECDSA_OID("1.2.840.10045.2.1");
Jeff Thompsonc0573432013-09-19 17:41:36 -070037
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080038PublicKey::PublicKey()
Yingdi Yu2620b1c2014-06-12 15:32:57 -070039 : m_type(KEY_TYPE_NULL)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080040{
Jeff Thompsonc0573432013-09-19 17:41:36 -070041}
Jeff Thompsonc0573432013-09-19 17:41:36 -070042
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070043PublicKey::PublicKey(const uint8_t* keyDerBuf, size_t keyDerSize)
Yingdi Yu2620b1c2014-06-12 15:32:57 -070044 : m_type(KEY_TYPE_NULL)
Jeff Thompsonc0573432013-09-19 17:41:36 -070045{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080046 StringSource src(keyDerBuf, keyDerSize, true);
47 decode(src);
Jeff Thompsonc0573432013-09-19 17:41:36 -070048}
49
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080050void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070051PublicKey::encode(CryptoPP::BufferedTransformation& out) const
Jeff Thompsonc0573432013-09-19 17:41:36 -070052{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080053 // SubjectPublicKeyInfo ::= SEQUENCE {
54 // algorithm AlgorithmIdentifier
55 // keybits BIT STRING }
56
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070057 out.Put(m_key.buf(), m_key.size());
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080058}
59
60void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070061PublicKey::decode(CryptoPP::BufferedTransformation& in)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080062{
63 // SubjectPublicKeyInfo ::= SEQUENCE {
64 // algorithm AlgorithmIdentifier
65 // keybits BIT STRING }
66
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070067 try
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080068 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070069 std::string out;
70 StringSink sink(out);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080071
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070072 ////////////////////////
73 // part 1: copy as is //
74 ////////////////////////
75 BERSequenceDecoder decoder(in);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080076 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070077 assert(decoder.IsDefiniteLength());
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080078
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070079 DERSequenceEncoder encoder(sink);
80 decoder.TransferTo(encoder, decoder.RemainingLength());
81 encoder.MessageEnd();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080082 }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070083 decoder.MessageEnd();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080084
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070085 ////////////////////////
86 // part 2: check if the key is RSA (since it is the only supported for now)
87 ////////////////////////
88 StringSource checkedSource(out, true);
89 BERSequenceDecoder subjectPublicKeyInfo(checkedSource);
90 {
91 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
92 {
93 OID algorithm;
94 algorithm.decode(algorithmInfo);
95
Yingdi Yu2620b1c2014-06-12 15:32:57 -070096 if (algorithm == RSA_OID)
97 m_type = KEY_TYPE_RSA;
98 else if (algorithm == ECDSA_OID)
99 m_type = KEY_TYPE_ECDSA;
100 else
101 throw Error("Only RSA/ECDSA public keys are supported for now (" +
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700102 algorithm.toString() + " requested)");
103 }
104 }
105
106 m_key.assign(out.begin(), out.end());
107 }
108 catch (CryptoPP::BERDecodeErr& err)
109 {
Yingdi Yu2620b1c2014-06-12 15:32:57 -0700110 m_type = KEY_TYPE_NULL;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700111 throw Error("PublicKey decoding error");
112 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800113}
114
115// Blob
116// PublicKey::getDigest(DigestAlgorithm digestAlgorithm) const
117// {
118// if (digestAlgorithm == DIGEST_ALGORITHM_SHA256) {
119// uint8_t digest[SHA256_DIGEST_LENGTH];
120// ndn_digestSha256(keyDer_.buf(), keyDer_.size(), digest);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700121
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800122// return Blob(digest, sizeof(digest));
123// }
124// else
125// throw UnrecognizedDigestAlgorithmException("Wrong format!");
126// }
127
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700128std::ostream&
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700129operator<<(std::ostream& os, const PublicKey& key)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800130{
131 CryptoPP::StringSource(key.get().buf(), key.get().size(), true,
132 new CryptoPP::Base64Encoder(new CryptoPP::FileSink(os), true, 64));
133
134 return os;
Jeff Thompsonc0573432013-09-19 17:41:36 -0700135}
136
Yingdi Yufc40d872014-02-18 12:56:04 -0800137} // namespace ndn