1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
using System;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Cms
{
/**
* General class for generating a compressed CMS message stream.
* <p>
* A simple example of usage.
* </p>
* <pre>
* CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator();
*
* Stream cOut = gen.Open(outputStream, CMSCompressedDataStreamGenerator.ZLIB);
*
* cOut.Write(data);
*
* cOut.Close();
* </pre>
*/
public class CmsCompressedDataStreamGenerator
{
public static readonly string ZLib = CmsObjectIdentifiers.ZlibCompress.Id;
private int _bufferSize;
/**
* base constructor
*/
public CmsCompressedDataStreamGenerator()
{
}
/**
* Set the underlying string size for encapsulated data
*
* @param bufferSize length of octet strings to buffer the data.
*/
public void SetBufferSize(int bufferSize)
{
_bufferSize = bufferSize;
}
public Stream Open(Stream outStream)
{
return Open(outStream, CmsObjectIdentifiers.Data.Id, ZLib);
}
public Stream Open(Stream outStream, string compressionOid)
{
return Open(outStream, CmsObjectIdentifiers.Data.Id, compressionOid);
}
public Stream Open(Stream outStream, string contentOid, string compressionOid)
{
if (ZLib != compressionOid)
throw new ArgumentException("Unsupported compression algorithm: " + compressionOid,
nameof(compressionOid));
BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);
sGen.AddObject(CmsObjectIdentifiers.CompressedData);
//
// Compressed Data
//
BerSequenceGenerator cGen = new BerSequenceGenerator(
sGen.GetRawOutputStream(), 0, true);
// CMSVersion
cGen.AddObject(new DerInteger(0));
// CompressionAlgorithmIdentifier
cGen.AddObject(new AlgorithmIdentifier(CmsObjectIdentifiers.ZlibCompress));
//
// Encapsulated ContentInfo
//
BerSequenceGenerator eiGen = new BerSequenceGenerator(cGen.GetRawOutputStream());
eiGen.AddObject(new DerObjectIdentifier(contentOid));
Stream octetStream = CmsUtilities.CreateBerOctetOutputStream(
eiGen.GetRawOutputStream(), 0, true, _bufferSize);
return new CmsCompressedOutputStream(
Utilities.IO.Compression.ZLib.CompressOutput(octetStream, -1), sGen, cGen, eiGen);
}
private class CmsCompressedOutputStream
: BaseOutputStream
{
private Stream _out;
private BerSequenceGenerator _sGen;
private BerSequenceGenerator _cGen;
private BerSequenceGenerator _eiGen;
internal CmsCompressedOutputStream(
Stream outStream,
BerSequenceGenerator sGen,
BerSequenceGenerator cGen,
BerSequenceGenerator eiGen)
{
_out = outStream;
_sGen = sGen;
_cGen = cGen;
_eiGen = eiGen;
}
public override void Write(byte[] buffer, int offset, int count)
{
_out.Write(buffer, offset, count);
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
public override void Write(ReadOnlySpan<byte> buffer)
{
_out.Write(buffer);
}
#endif
public override void WriteByte(byte value)
{
_out.WriteByte(value);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Platform.Dispose(_out);
// TODO Parent context(s) should really be be closed explicitly
_eiGen.Close();
_cGen.Close();
_sGen.Close();
}
base.Dispose(disposing);
}
}
}
}
|