internal static byte[][] SegmentedEncodeOid(Oid oid)
{
Debug.Assert(oid != null);
// All exceptions past this point should just be "CryptographicException", because that's
// how they'd come back from Desktop/Windows, since it was a non-success result of calling
// CryptEncodeObject.
string oidValue = oid.Value;
if (string.IsNullOrEmpty(oidValue))
throw new CryptographicException(SR.Argument_InvalidOidValue);
if (oidValue.Length < 3 /* "1.1" is the shortest value */)
throw new CryptographicException(SR.Argument_InvalidOidValue);
if (oidValue[1] != '.')
throw new CryptographicException(SR.Argument_InvalidOidValue);
int firstRid;
switch (oidValue[0])
{
case '0':
firstRid = 0;
break;
case '1':
firstRid = 1;
break;
case '2':
firstRid = 2;
break;
default:
throw new CryptographicException(SR.Argument_InvalidOidValue);
}
int startPos = 2;
// The first two RIDs are special:
// ITU X.690 8.19.4:
// The numerical value of the first subidentifier is derived from the values of the first two
// object identifier components in the object identifier value being encoded, using the formula:
// (X*40) + Y
// where X is the value of the first object identifier component and Y is the value of the
// second object identifier component.
// NOTE – This packing of the first two object identifier components recognizes that only
// three values are allocated from the root node, and at most 39 subsequent values from
// nodes reached by X = 0 and X = 1.
BigInteger rid = ParseOidRid(oidValue, ref startPos);
rid += 40 * firstRid;
// The worst case is "1.1.1.1.1", which takes 4 bytes (5 rids, with the first two condensed)
// Longer numbers get smaller: "2.1.127" is only 2 bytes. (81d (0x51) and 127 (0x7F))
// So length / 2 should prevent any reallocations.
List<byte> encodedBytes = new List<byte>(oidValue.Length / 2);
EncodeRid(encodedBytes, ref rid);
while (startPos < oidValue.Length)
{
rid = ParseOidRid(oidValue, ref startPos);
EncodeRid(encodedBytes, ref rid);
}
return new byte[][]
{
new byte[] { (byte)DerSequenceReader.DerTag.ObjectIdentifier },
EncodeLength(encodedBytes.Count),
encodedBytes.ToArray(),
};
}