blob: 205dcd2ce6dce617315162b7c83cc334b26cf448 [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>
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080010#include <ndn-cpp/security/certificate/public-key.hpp>
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080011
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080012#if NDN_CPP_USE_SYSTEM_BOOST
13#include <boost/iostreams/stream.hpp>
14#include <boost/iostreams/device/array.hpp>
15namespace ndnboost = boost;
16#else
Jeff Thompson07996712013-10-17 17:31:40 -070017// We can use ndnboost::iostreams because this is internal and will not conflict with the application if it uses boost::iostreams.
18#include <ndnboost/iostreams/stream.hpp>
19#include <ndnboost/iostreams/device/array.hpp>
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080020#endif
21
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080022#include <cryptopp/rsa.h>
23#include <cryptopp/base64.h>
24#include <cryptopp/files.h>
Jeff Thompsonc0573432013-09-19 17:41:36 -070025
26using namespace std;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080027using namespace CryptoPP;
Jeff Thompsonc0573432013-09-19 17:41:36 -070028
29namespace ndn {
30
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080031static OID RSA_OID("1.2.840.113549.1.1.1");
Jeff Thompsonc0573432013-09-19 17:41:36 -070032
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080033PublicKey::PublicKey()
34{
Jeff Thompsonc0573432013-09-19 17:41:36 -070035}
Jeff Thompsonc0573432013-09-19 17:41:36 -070036
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080037/**
38 * Create a new PublicKey with the given values.
39 * @param algorithm The algorithm of the public key.
40 * @param keyDer The blob of the PublicKeyInfo in terms of DER.
41 */
42PublicKey::PublicKey(const uint8_t *keyDerBuf, size_t keyDerSize)
Jeff Thompsonc0573432013-09-19 17:41:36 -070043{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080044 StringSource src(keyDerBuf, keyDerSize, true);
45 decode(src);
Jeff Thompsonc0573432013-09-19 17:41:36 -070046}
47
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080048void
49PublicKey::encode(CryptoPP::BufferedTransformation &out) const
Jeff Thompsonc0573432013-09-19 17:41:36 -070050{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080051 // SubjectPublicKeyInfo ::= SEQUENCE {
52 // algorithm AlgorithmIdentifier
53 // keybits BIT STRING }
54
55 out.Put(key_.buf(), key_.size());
56}
57
58void
59PublicKey::decode(CryptoPP::BufferedTransformation &in)
60{
61 // SubjectPublicKeyInfo ::= SEQUENCE {
62 // algorithm AlgorithmIdentifier
63 // keybits BIT STRING }
64
65 try {
66 std::string out;
67 StringSink sink(out);
68
69 ////////////////////////
70 // part 1: copy as is //
71 ////////////////////////
72 BERSequenceDecoder decoder(in);
73 {
74 assert (decoder.IsDefiniteLength());
75
76 DERSequenceEncoder encoder(sink);
77 decoder.TransferTo(encoder, decoder.RemainingLength());
78 encoder.MessageEnd();
79 }
80 decoder.MessageEnd();
81
82 ////////////////////////
83 // part 2: check if the key is RSA (since it is the only supported for now)
84 ////////////////////////
85 StringSource checkedSource(out, true);
86 BERSequenceDecoder subjectPublicKeyInfo(checkedSource);
87 {
88 BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
89 {
90 OID algorithm;
91 algorithm.decode(algorithmInfo);
92
93 if (algorithm != RSA_OID)
94 throw Error("Only RSA public keys are supported for now (" + algorithm.toString() + " requested");
95 }
96 }
97
98 key_.assign(out.begin(), out.end());
Jeff Thompsonc0573432013-09-19 17:41:36 -070099 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800100 catch (CryptoPP::BERDecodeErr &err) {
101 throw Error("PublicKey decoding error");
102 }
103}
104
105// Blob
106// PublicKey::getDigest(DigestAlgorithm digestAlgorithm) const
107// {
108// if (digestAlgorithm == DIGEST_ALGORITHM_SHA256) {
109// uint8_t digest[SHA256_DIGEST_LENGTH];
110// ndn_digestSha256(keyDer_.buf(), keyDer_.size(), digest);
111
112// return Blob(digest, sizeof(digest));
113// }
114// else
115// throw UnrecognizedDigestAlgorithmException("Wrong format!");
116// }
117
118std::ostream &
119operator <<(std::ostream &os, const PublicKey &key)
120{
121 CryptoPP::StringSource(key.get().buf(), key.get().size(), true,
122 new CryptoPP::Base64Encoder(new CryptoPP::FileSink(os), true, 64));
123
124 return os;
Jeff Thompsonc0573432013-09-19 17:41:36 -0700125}
126
127}