blob: 131e3c14aa905b819721bc492d9b7a208781a0df [file] [log] [blame]
Jeff Thompsonc0573432013-09-19 17:41:36 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
6 * See COPYING for copyright and distribution information.
7 */
8
Alexander Afanasyev8e96e582013-11-19 12:07:04 -08009#include <ndn-cpp/common.hpp>
10
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080011#include "public-key.hpp"
12
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080013#if NDN_CPP_USE_SYSTEM_BOOST
14#include <boost/iostreams/stream.hpp>
15#include <boost/iostreams/device/array.hpp>
16namespace ndnboost = boost;
17#else
Jeff Thompson07996712013-10-17 17:31:40 -070018// We can use ndnboost::iostreams because this is internal and will not conflict with the application if it uses boost::iostreams.
19#include <ndnboost/iostreams/stream.hpp>
20#include <ndnboost/iostreams/device/array.hpp>
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080021#endif
22
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080023#include <cryptopp/rsa.h>
24#include <cryptopp/base64.h>
25#include <cryptopp/files.h>
Jeff Thompsonc0573432013-09-19 17:41:36 -070026
27using namespace std;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080028using namespace CryptoPP;
Jeff Thompsonc0573432013-09-19 17:41:36 -070029
30namespace ndn {
31
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080032static OID RSA_OID("1.2.840.113549.1.1.1");
Jeff Thompsonc0573432013-09-19 17:41:36 -070033
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080034PublicKey::PublicKey()
35{
Jeff Thompsonc0573432013-09-19 17:41:36 -070036}
Jeff Thompsonc0573432013-09-19 17:41:36 -070037
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080038/**
39 * Create a new PublicKey with the given values.
40 * @param algorithm The algorithm of the public key.
41 * @param keyDer The blob of the PublicKeyInfo in terms of DER.
42 */
43PublicKey::PublicKey(const uint8_t *keyDerBuf, size_t keyDerSize)
Jeff Thompsonc0573432013-09-19 17:41:36 -070044{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080045 StringSource src(keyDerBuf, keyDerSize, true);
46 decode(src);
Jeff Thompsonc0573432013-09-19 17:41:36 -070047}
48
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080049void
50PublicKey::encode(CryptoPP::BufferedTransformation &out) const
Jeff Thompsonc0573432013-09-19 17:41:36 -070051{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080052 // SubjectPublicKeyInfo ::= SEQUENCE {
53 // algorithm AlgorithmIdentifier
54 // keybits BIT STRING }
55
56 out.Put(key_.buf(), key_.size());
57}
58
59void
60PublicKey::decode(CryptoPP::BufferedTransformation &in)
61{
62 // SubjectPublicKeyInfo ::= SEQUENCE {
63 // algorithm AlgorithmIdentifier
64 // keybits BIT STRING }
65
66 try {
67 std::string out;
68 StringSink sink(out);
69
70 ////////////////////////
71 // part 1: copy as is //
72 ////////////////////////
73 BERSequenceDecoder decoder(in);
74 {
75 assert (decoder.IsDefiniteLength());
76
77 DERSequenceEncoder encoder(sink);
78 decoder.TransferTo(encoder, decoder.RemainingLength());
79 encoder.MessageEnd();
80 }
81 decoder.MessageEnd();
82
83 ////////////////////////
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
94 if (algorithm != RSA_OID)
95 throw Error("Only RSA public keys are supported for now (" + algorithm.toString() + " requested");
96 }
97 }
98
99 key_.assign(out.begin(), out.end());
Jeff Thompsonc0573432013-09-19 17:41:36 -0700100 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800101 catch (CryptoPP::BERDecodeErr &err) {
102 throw Error("PublicKey decoding error");
103 }
104}
105
106// Blob
107// PublicKey::getDigest(DigestAlgorithm digestAlgorithm) const
108// {
109// if (digestAlgorithm == DIGEST_ALGORITHM_SHA256) {
110// uint8_t digest[SHA256_DIGEST_LENGTH];
111// ndn_digestSha256(keyDer_.buf(), keyDer_.size(), digest);
112
113// return Blob(digest, sizeof(digest));
114// }
115// else
116// throw UnrecognizedDigestAlgorithmException("Wrong format!");
117// }
118
119std::ostream &
120operator <<(std::ostream &os, const PublicKey &key)
121{
122 CryptoPP::StringSource(key.get().buf(), key.get().size(), true,
123 new CryptoPP::Base64Encoder(new CryptoPP::FileSink(os), true, 64));
124
125 return os;
Jeff Thompsonc0573432013-09-19 17:41:36 -0700126}
127
128}