/src/PcapPlusPlus/Packet++/src/PemCodec.cpp
Line | Count | Source |
1 | | #include "PemCodec.h" |
2 | | #include "GeneralUtils.h" |
3 | | #include <sstream> |
4 | | #include <iostream> |
5 | | #include <algorithm> |
6 | | |
7 | | namespace pcpp |
8 | | { |
9 | | std::string PemCodec::encode(const std::vector<uint8_t>& data, const std::string& label) |
10 | 0 | { |
11 | 0 | if (label.empty()) |
12 | 0 | { |
13 | 0 | throw std::invalid_argument("PEM label cannot be empty"); |
14 | 0 | } |
15 | | |
16 | 0 | if (data.empty()) |
17 | 0 | { |
18 | 0 | throw std::invalid_argument("PEM data cannot be empty"); |
19 | 0 | } |
20 | | |
21 | 0 | auto base64Str = Base64::encode(data); |
22 | 0 | std::ostringstream oss; |
23 | |
|
24 | 0 | oss << pemBegin << label << pemDelimiter << "\n"; |
25 | |
|
26 | 0 | auto base64StrSize = base64Str.size(); |
27 | 0 | for (size_t i = 0; i < base64StrSize; i += lineLength) |
28 | 0 | { |
29 | 0 | auto len = base64StrSize - i < lineLength ? base64StrSize - i : lineLength; |
30 | 0 | oss.write(&base64Str[i], len); |
31 | 0 | oss.put('\n'); |
32 | 0 | } |
33 | |
|
34 | 0 | oss << pemEnd << label << pemDelimiter << "\n"; |
35 | 0 | return oss.str(); |
36 | 0 | } |
37 | | |
38 | | std::vector<uint8_t> PemCodec::decode(const std::string& pemData, const std::string& expectedLabel) |
39 | 0 | { |
40 | 0 | std::istringstream iss(pemData); |
41 | 0 | std::string line; |
42 | 0 | std::string base64Data; |
43 | 0 | std::string beginLabel, endLabel; |
44 | 0 | bool inBody = false; |
45 | |
|
46 | 0 | while (std::getline(iss, line)) |
47 | 0 | { |
48 | 0 | line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); |
49 | |
|
50 | 0 | if (line.find(pemBegin) == 0) |
51 | 0 | { |
52 | 0 | if (inBody) |
53 | 0 | { |
54 | 0 | throw std::invalid_argument("Unexpected BEGIN while already inside a PEM block"); |
55 | 0 | } |
56 | | |
57 | 0 | beginLabel = line.substr(pemBeginLen, line.find(pemDelimiter, pemBeginLen) - pemBeginLen); |
58 | 0 | if (beginLabel.empty()) |
59 | 0 | { |
60 | 0 | throw std::invalid_argument("Invalid BEGIN label in PEM"); |
61 | 0 | } |
62 | | |
63 | 0 | if (!expectedLabel.empty() && beginLabel != expectedLabel) |
64 | 0 | { |
65 | 0 | throw std::invalid_argument("Unexpected BEGIN label in PEM - expected '" + expectedLabel + |
66 | 0 | "' but got '" + beginLabel + "'"); |
67 | 0 | } |
68 | | |
69 | 0 | if (line.compare(line.size() - pemDelimiterLen, pemDelimiterLen, pemDelimiter) != 0) |
70 | 0 | { |
71 | 0 | throw std::invalid_argument("Invalid BEGIN suffix in PEM"); |
72 | 0 | } |
73 | | |
74 | 0 | inBody = true; |
75 | 0 | continue; |
76 | 0 | } |
77 | | |
78 | 0 | if (line.find(pemEnd) == 0) |
79 | 0 | { |
80 | 0 | if (!inBody) |
81 | 0 | { |
82 | 0 | throw std::invalid_argument("END found before BEGIN in PEM"); |
83 | 0 | } |
84 | | |
85 | 0 | endLabel = line.substr(pemEndLen, line.find(pemDelimiter, pemEndLen) - pemEndLen); |
86 | 0 | if (endLabel != beginLabel) |
87 | 0 | { |
88 | 0 | throw std::invalid_argument("BEGIN and END labels do not match in PEM"); |
89 | 0 | } |
90 | 0 | break; |
91 | 0 | } |
92 | | |
93 | 0 | if (inBody && !line.empty()) |
94 | 0 | { |
95 | 0 | base64Data += line; |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | 0 | if (beginLabel.empty() || endLabel.empty()) |
100 | 0 | { |
101 | 0 | throw std::invalid_argument("Missing BEGIN or END in PEM data"); |
102 | 0 | } |
103 | | |
104 | 0 | if (base64Data.empty()) |
105 | 0 | { |
106 | 0 | throw std::invalid_argument("No base64 content found in PEM data"); |
107 | 0 | } |
108 | | |
109 | 0 | return Base64::decodeToByteVector(base64Data); |
110 | 0 | } |
111 | | } // namespace pcpp |