<?xml version="1.0" encoding="utf-8"?>
<root>
- <!--
- Microsoft ResX Schema
-
+ <!--
+ Microsoft ResX Schema
+
Version 2.0
-
- The primary goals of this format is to allow a simple XML format
- that is mostly human readable. The generation and parsing of the
- various data types are done through the TypeConverter classes
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
associated with the data types.
-
+
Example:
-
+
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
-
- There are any number of "resheader" rows that contain simple
+
+ There are any number of "resheader" rows that contain simple
name/value pairs.
-
- Each data row contains a name, and value. The row also contains a
- type or mimetype. Type corresponds to a .NET class that support
- text/value conversion through the TypeConverter architecture.
- Classes that don't support this are serialized and stored with the
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
mimetype set.
-
- The mimetype is used for serialized objects, and tells the
- ResXResourceReader how to depersist the object. This is currently not
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
-
- Note - application/x-microsoft.net.object.binary.base64 is the format
- that the ResXResourceWriter will generate, however the reader can
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
-
+
mimetype: application/x-microsoft.net.object.binary.base64
- value : The object must be serialized with
+ value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
-
+
mimetype: application/x-microsoft.net.object.soap.base64
- value : The object must be serialized with
+ value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
- value : The object must be serialized into a byte array
+ value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<value>Label in Critical Headers array was incorrect.</value>
</data>
<data name="CriticalHeadersMustBeArrayOfAtLeastOne" xml:space="preserve">
- <value>Critical Headers must be a definite-length CBOR array of at least one element.</value>
+ <value>Critical Headers must be a CBOR array of at least one element.</value>
</data>
<data name="DecodeCoseSignatureMustBeArrayOfThree" xml:space="preserve">
- <value>COSE Signature must be a definite-length array of 3 elements.</value>
+ <value>COSE Signature must be an array of three elements.</value>
</data>
<data name="DecodeErrorWhileDecoding" xml:space="preserve">
<value>Error while decoding COSE message. {0}</value>
<data name="DecodeMessageContainedTrailingData" xml:space="preserve">
<value>CBOR payload contained trailing data after message was complete.</value>
</data>
+ <data name="DecodeMultiSignArrayLengthMustBeFour" xml:space="preserve">
+ <value>COSE_Sign must be an array of four elements.</value>
+ </data>
<data name="DecodeMultiSignIncorrectTag" xml:space="preserve">
<value>Incorrect tag. Expected Sign(98) or Untagged, Actual '{0}'.</value>
</data>
<data name="DecodeSign1ArrayLengthMustBeFour" xml:space="preserve">
- <value>Array length for COSE_Sign1 must be four.</value>
+ <value>COSE_Sign1 must be an array of four elements.</value>
</data>
<data name="DecodeSign1EncodedProtectedMapIncorrect" xml:space="preserve">
<value>Protected map was incorrect.</value>
<data name="Sign1VerifyAlgIsRequired" xml:space="preserve">
<value>Algorithm (alg) header is required and it must be a protected header.</value>
</data>
-</root>
+</root>
\ No newline at end of file
reader.SkipValue();
break;
case KnownHeaders.Crit:
- int length = reader.ReadStartArray().GetValueOrDefault();
- if (length < 1)
- {
- throw new ArgumentException(SR.CriticalHeadersMustBeArrayOfAtLeastOne, nameof(value));
- }
+ reader.ReadStartArray();
+ bool isEmpty = true;
- for (int i = 0; i < length; i++)
+ while (true)
{
CborReaderState state = reader.PeekState();
- if (state == CborReaderState.UnsignedInteger || state == CborReaderState.NegativeInteger)
+ if (state == CborReaderState.EndArray)
+ {
+ reader.ReadEndArray();
+ break;
+ }
+ else if (state == CborReaderState.UnsignedInteger || state == CborReaderState.NegativeInteger)
{
reader.ReadInt32();
}
{
throw new ArgumentException(SR.Format(SR.CoseHeaderMapHeaderDoesNotAcceptSpecifiedValue, label.LabelName), nameof(value));
}
+ isEmpty = false;
+ }
+
+ if (isEmpty)
+ {
+ throw new ArgumentException(SR.CriticalHeadersMustBeArrayOfAtLeastOne, nameof(value));
}
- reader.SkipToParent();
break;
case KnownHeaders.ContentType:
if (initialState != CborReaderState.TextString &&
throw new CryptographicException(SR.Format(SR.DecodeSign1IncorrectTag, tag));
}
+ ReadOnlyMemory<byte> coseSignArray = reader.ReadEncodedValue();
+
+ if (reader.BytesRemaining != 0)
+ {
+ throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMessageContainedTrailingData));
+ }
+
+ reader = new CborReader(coseSignArray);
+
int? arrayLength = reader.ReadStartArray();
- if (arrayLength != 4)
+ if (arrayLength.HasValue ? arrayLength != CoseSign1Message.Sign1ArrayLength :
+ HasIndefiniteLengthArrayIncorrectLength(coseSignArray, CoseSign1Message.Sign1ArrayLength))
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeSign1ArrayLengthMustBeFour));
}
byte[] signature = DecodeSignature(reader);
reader.ReadEndArray();
- if (reader.BytesRemaining != 0)
- {
- throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMessageContainedTrailingData));
- }
+ Debug.Assert(reader.BytesRemaining == 0);
return new CoseSign1Message(protectedHeader, unprotectedHeader, payload, signature, protectedHeaderAsBstr, tag.HasValue);
}
throw new CryptographicException(SR.Format(SR.DecodeMultiSignIncorrectTag, tag));
}
+ ReadOnlyMemory<byte> coseSignArray = reader.ReadEncodedValue();
+
+ if (reader.BytesRemaining != 0)
+ {
+ throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMessageContainedTrailingData));
+ }
+
+ reader = new CborReader(coseSignArray);
+
int? arrayLength = reader.ReadStartArray();
- if (arrayLength != 4)
+ if (arrayLength.HasValue ? arrayLength != CoseMultiSignMessage.MultiSignArrayLength :
+ HasIndefiniteLengthArrayIncorrectLength(coseSignArray, CoseMultiSignMessage.MultiSignArrayLength))
{
- throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeSign1ArrayLengthMustBeFour));
+ throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMultiSignArrayLengthMustBeFour));
}
var protectedHeaders = new CoseHeaderMap();
}
byte[]? payload = DecodePayload(reader);
- List<CoseSignature> signatures = DecodeCoseSignaturesArray(reader, encodedProtectedHeaders);
+ List<CoseSignature> signatures = DecodeCoseSignaturesArray(reader);
reader.ReadEndArray();
-
- if (reader.BytesRemaining != 0)
- {
- throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeMessageContainedTrailingData));
- }
+ Debug.Assert(reader.BytesRemaining == 0);
return new CoseMultiSignMessage(protectedHeaders, unprotectedHeaders, payload, signatures, encodedProtectedHeaders, tag.HasValue);
}
return reader.ReadByteString();
}
- private static List<CoseSignature> DecodeCoseSignaturesArray(CborReader reader, byte[] bodyProtected)
+ private static List<CoseSignature> DecodeCoseSignaturesArray(CborReader reader)
{
int? signaturesLength = reader.ReadStartArray();
+ List<CoseSignature> signatures = new List<CoseSignature>(signaturesLength.GetValueOrDefault());
+
+ while (reader.PeekState() == CborReaderState.StartArray)
+ {
+ CoseSignature signature = DecodeCoseSignature(reader.ReadEncodedValue());
+ signatures.Add(signature);
+ }
+
+ reader.ReadEndArray();
- if (signaturesLength.GetValueOrDefault() < 1)
+ if (signatures.Count < 1)
{
throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.MultiSignMessageMustCarryAtLeastOneSignature));
}
- List<CoseSignature> signatures = new List<CoseSignature>(signaturesLength!.Value);
+ return signatures;
+ }
- for (int i = 0; i < signaturesLength; i++)
+ private static CoseSignature DecodeCoseSignature(ReadOnlyMemory<byte> coseSignature)
+ {
+ var reader = new CborReader(coseSignature);
+ int? length = reader.ReadStartArray();
+
+ if (length.HasValue ? length != CoseMultiSignMessage.CoseSignatureArrayLength :
+ HasIndefiniteLengthArrayIncorrectLength(coseSignature, CoseMultiSignMessage.CoseSignatureArrayLength))
{
- int? length = reader.ReadStartArray();
+ throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeCoseSignatureMustBeArrayOfThree));
+ }
- if (length != CoseMultiSignMessage.CoseSignatureArrayLength)
- {
- throw new CryptographicException(SR.Format(SR.DecodeErrorWhileDecoding, SR.DecodeCoseSignatureMustBeArrayOfThree));
- }
+ var protectedHeaders = new CoseHeaderMap();
+ DecodeProtectedBucket(reader, protectedHeaders, out byte[] signProtected);
- var protectedHeaders = new CoseHeaderMap();
- DecodeProtectedBucket(reader, protectedHeaders, out byte[] signProtected);
+ var unprotectedHeaders = new CoseHeaderMap();
+ DecodeUnprotectedBucket(reader, unprotectedHeaders);
- var unprotectedHeaders = new CoseHeaderMap();
- DecodeUnprotectedBucket(reader, unprotectedHeaders);
+ if (ContainDuplicateLabels(protectedHeaders, unprotectedHeaders))
+ {
+ throw new CryptographicException(SR.Sign1SignHeaderDuplicateLabels);
+ }
- if (ContainDuplicateLabels(protectedHeaders, unprotectedHeaders))
- {
- throw new CryptographicException(SR.Sign1SignHeaderDuplicateLabels);
- }
+ byte[] signatureBytes = DecodeSignature(reader);
+ reader.ReadEndArray();
- byte[] signatureBytes = DecodeSignature(reader);
+ return new CoseSignature(protectedHeaders, unprotectedHeaders, signProtected, signatureBytes);
+ }
- signatures.Add(new CoseSignature(protectedHeaders, unprotectedHeaders, bodyProtected, signProtected, signatureBytes));
+ private static bool HasIndefiniteLengthArrayIncorrectLength(ReadOnlyMemory<byte> encodedArray, int expectedLength)
+ {
+ var reader = new CborReader(encodedArray);
+ reader.ReadStartArray();
+ int count = 0;
- reader.ReadEndArray();
+ while (reader.PeekState() != CborReaderState.EndArray)
+ {
+ reader.SkipValue();
+ count++;
+
+ if (count > expectedLength)
+ {
+ return true;
+ }
}
+
+ bool retVal = count != expectedLength;
reader.ReadEndArray();
+ Debug.Assert(reader.BytesRemaining == 0);
- return signatures;
+ return retVal;
}
internal static void AppendToBeSigned(
/// </summary>
public sealed class CoseMultiSignMessage : CoseMessage
{
- private const int MultiSignArrayLength = 4;
+ internal const int MultiSignArrayLength = 4;
private const int MultiSignSizeOfCborTag = 2;
internal const int CoseSignatureArrayLength = 3;
bytesWritten = CoseHelpers.SignHash(signer, hasher, buffer);
byte[] signature = bufferSpan.Slice(0, bytesWritten).ToArray();
- _signatures.Add(new CoseSignature(this, signProtectedHeaders, signer.UnprotectedHeaders, _protectedHeaderAsBstr, encodedSignProtected, signature));
+ _signatures.Add(new CoseSignature(this, signProtectedHeaders, signer.UnprotectedHeaders, encodedSignProtected, signature));
}
}
finally
bytesWritten = CoseHelpers.SignHash(signer, hasher, buffer);
byte[] signature = buffer.AsSpan(0, bytesWritten).ToArray();
- _signatures.Add(new CoseSignature(this, signProtectedHeaders, signer.UnprotectedHeaders, _protectedHeaderAsBstr, encodedSignProtected, signature));
+ _signatures.Add(new CoseSignature(this, signProtectedHeaders, signer.UnprotectedHeaders, encodedSignProtected, signature));
}
ArrayPool<byte>.Shared.Return(buffer, clearArray: true);
/// </summary>
public sealed class CoseSign1Message : CoseMessage
{
- private const int Sign1ArrayLength = 4;
+ internal const int Sign1ArrayLength = 4;
private const int Sign1SizeOfCborTag = 1;
private readonly byte[] _signature;
/// </summary>
public sealed class CoseSignature
{
- private readonly byte[] _encodedBodyProtectedHeaders;
internal readonly byte[] _encodedSignProtectedHeaders;
internal readonly byte[] _signature;
private CoseMultiSignMessage? _message;
/// <value>A region of memory that contains the digital signature.</value>
public ReadOnlyMemory<byte> Signature => _signature;
- internal CoseSignature(CoseMultiSignMessage message, CoseHeaderMap protectedHeaders, CoseHeaderMap unprotectedHeaders, byte[] encodedBodyProtectedHeaders, byte[] encodedSignProtectedHeaders, byte[] signature)
- : this(protectedHeaders, unprotectedHeaders, encodedBodyProtectedHeaders, encodedSignProtectedHeaders, signature)
+ internal CoseSignature(CoseMultiSignMessage message, CoseHeaderMap protectedHeaders, CoseHeaderMap unprotectedHeaders, byte[] encodedSignProtectedHeaders, byte[] signature)
+ : this(protectedHeaders, unprotectedHeaders, encodedSignProtectedHeaders, signature)
{
Message = message;
}
- internal CoseSignature(CoseHeaderMap protectedHeaders, CoseHeaderMap unprotectedHeaders, byte[] encodedBodyProtectedHeaders, byte[] encodedSignProtectedHeaders, byte[] signature)
+ internal CoseSignature(CoseHeaderMap protectedHeaders, CoseHeaderMap unprotectedHeaders, byte[] encodedSignProtectedHeaders, byte[] signature)
{
ProtectedHeaders = protectedHeaders;
UnprotectedHeaders = unprotectedHeaders;
- _encodedBodyProtectedHeaders = encodedBodyProtectedHeaders;
_encodedSignProtectedHeaders = encodedSignProtectedHeaders;
_signature = signature;
}
{
int bufferLength = CoseMessage.ComputeToBeSignedEncodedSize(
SigStructureContext.Signature,
- _encodedBodyProtectedHeaders.Length,
+ Message.RawProtectedHeaders.Length,
_encodedSignProtectedHeaders.Length,
associatedData.Length,
contentLength: 0);
try
{
- await CoseMessage.AppendToBeSignedAsync(buffer, hasher, SigStructureContext.Signature, _encodedBodyProtectedHeaders, _encodedSignProtectedHeaders, associatedData, content, cancellationToken).ConfigureAwait(false);
+ await CoseMessage.AppendToBeSignedAsync(buffer, hasher, SigStructureContext.Signature, Message.RawProtectedHeaders, _encodedSignProtectedHeaders, associatedData, content, cancellationToken).ConfigureAwait(false);
return VerifyHash(key, hasher, hashAlgorithm, keyType, padding);
}
finally
{
int bufferLength = CoseMessage.ComputeToBeSignedEncodedSize(
SigStructureContext.Signature,
- _encodedBodyProtectedHeaders.Length,
+ Message.RawProtectedHeaders.Length,
_encodedSignProtectedHeaders.Length,
associatedData.Length,
contentLength: 0);
try
{
- CoseMessage.AppendToBeSigned(buffer, hasher, SigStructureContext.Signature, _encodedBodyProtectedHeaders, _encodedSignProtectedHeaders, associatedData, contentBytes, contentStream);
+ CoseMessage.AppendToBeSigned(buffer, hasher, SigStructureContext.Signature, Message.RawProtectedHeaders.Span, _encodedSignProtectedHeaders, associatedData, contentBytes, contentStream);
return VerifyHash(key, hasher, hashAlgorithm, keyType, padding);
}
finally
Assert.Equal(1, map.Count);
}
+ [Fact]
+ public void SetEncodedValue_CriticalHeaders_ThrowIf_ArrayEmpty()
+ {
+ // definite length
+ var writer = new CborWriter();
+ writer.WriteStartArray(0);
+ writer.WriteEndArray();
+
+ Verify(writer.Encode());
+
+ // indefinite length
+ writer.Reset();
+ writer.WriteStartArray(null);
+ writer.WriteEndArray();
+
+ Verify(writer.Encode());
+
+ void Verify(byte[] encodedValue)
+ {
+ CoseHeaderMap map = new();
+ CoseHeaderValue value = CoseHeaderValue.FromEncodedValue(writer.Encode());
+ Assert.Throws<ArgumentException>(() => map[CoseHeaderLabel.CriticalHeaders] = value);
+ }
+ }
+
+ [Fact]
+ public void SetEncodedValue_CriticalHeaders_ThrowIf_IndefiniteLengthArrayMissingBreak()
+ {
+ byte[] encodedValue = GetDummyCritHeaderValue(useIndefiniteLength: true);
+
+ CoseHeaderMap map = new();
+ CoseHeaderValue value = CoseHeaderValue.FromEncodedValue(encodedValue.AsSpan(0, encodedValue.Length - 1));
+ Assert.Throws<ArgumentException>(() => map[CoseHeaderLabel.CriticalHeaders] = value);
+ }
+
public enum SetValueMethod
{
ItemSet,
writer.WriteInt32((int)ECDsaAlgorithm.ES256);
yield return ReturnDataAndReset(KnownHeaderAlg, writer, setMethod, getMethod);
- WriteDummyCritHeaderValue(writer);
+ WriteDummyCritHeaderValue(writer, useIndefiniteLength: false);
+ yield return ReturnDataAndReset(KnownHeaderCrit, writer, setMethod, getMethod);
+
+
+ WriteDummyCritHeaderValue(writer, useIndefiniteLength: true);
yield return ReturnDataAndReset(KnownHeaderCrit, writer, setMethod, getMethod);
writer.WriteTextString(ContentTypeDummyValue);
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Formats.Cbor;
using Test.Cryptography;
writer.WriteEndArray();
Assert.Throws<CryptographicException>(() => CoseMessage.DecodeMultiSign(writer.Encode()));
}
+
+ [Theory]
+ // COSE_Sign is an indefinite-length array
+ [InlineData("D8629F40A054546869732069732074686520636F6E74656E742E818343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30AFF")]
+ // [+COSE_Signature]
+ [InlineData("D8628440A054546869732069732074686520636F6E74656E742E9F8343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30AFF")]
+ // COSE_Signature
+ [InlineData("D8628440A054546869732069732074686520636F6E74656E742E819F43A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30AFF")]
+ // All of them
+ [InlineData("D8629F40A054546869732069732074686520636F6E74656E742E9F9F43A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30AFFFFFF")]
+ public void DecodeMultiSign_IndefiniteLengthArray(string hexCborPayload)
+ {
+ byte[] cborPayload = ByteUtils.HexToByteArray(hexCborPayload);
+ CoseMultiSignMessage msg = CoseMessage.DecodeMultiSign(cborPayload);
+
+ ReadOnlyCollection<CoseSignature> signatures = msg.Signatures;
+ Assert.Equal(1, signatures.Count);
+ Assert.True(signatures[0].VerifyEmbedded(DefaultKey));
+ }
+
+ [Theory]
+ // COSE_Sign
+ [InlineData("D8629F40A054546869732069732074686520636F6E74656E742E818343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A")]
+ // [+COSE_Signature]
+ [InlineData("D8628440A054546869732069732074686520636F6E74656E742E9F8343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A")]
+ // COSE_Signature
+ [InlineData("D8628440A054546869732069732074686520636F6E74656E742E819F43A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A")]
+ public void DecodeMultiSign_IndefiniteLengthArray_MissingBreak(string hexCborPayload)
+ {
+ byte[] cborPayload = ByteUtils.HexToByteArray(hexCborPayload);
+ CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeMultiSign(cborPayload));
+ Assert.IsType<CborContentException>(ex.InnerException);
+ }
+
+ // All these payloads contain one extra element of type byte string.
+ [Theory]
+ // COSE_Sign
+ [InlineData("D8629F40A054546869732069732074686520636F6E74656E742E818343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A40FF")]
+ // [+COSE_Signature] - this structure does not have a fixed length required, but the byte string is unexpected.
+ [InlineData("D8628440A054546869732069732074686520636F6E74656E742E9F8343A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A40FF")]
+ // COSE_Signature
+ [InlineData("D8628440A054546869732069732074686520636F6E74656E742E819F43A10126A1044231315840E2AEAFD40D69D19DFE6E52077C5D7FF4E408282CBEFB5D06CBF414AF2E19D982AC45AC98B8544C908B4507DE1E90B717C3D34816FE926A2B98F53AFD2FA0F30A40FF")]
+ public void DecodeMultiSign_IndefiniteLengthArray_LargerByOne(string hexCborPayload)
+ {
+ byte[] cborPayload = ByteUtils.HexToByteArray(hexCborPayload);
+ CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeMultiSign(cborPayload));
+ }
+
+ [Theory]
+ // COSE_Sign
+ [InlineData("D8629F40A054546869732069732074686520636F6E74656E742EFF")]
+ // [+COSE_Signature]
+ [InlineData("D8628440A054546869732069732074686520636F6E74656E742E9FFF")]
+ // COSE_Signature
+ [InlineData("D8628440A054546869732069732074686520636F6E74656E742E819F43A10126A104423131FF")]
+ public void DecodeMultiSign_IndefiniteLengthArray_ShorterByOne(string hexCborPayload)
+ {
+ byte[] cborPayload = ByteUtils.HexToByteArray(hexCborPayload);
+ CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeMultiSign(cborPayload));
+ Assert.Null(ex.InnerException);
+ }
}
}
writer.WriteEndArray();
Assert.Throws<CryptographicException>(() => CoseMessage.DecodeSign1(writer.Encode()));
}
+
+ [Fact]
+ public void DecodeSign1_IndefiniteLengthArray()
+ {
+ byte[] cborPayload = ByteUtils.HexToByteArray("D29F43A10126A10442313154546869732069732074686520636F6E74656E742E58408EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36FF");
+ CoseSign1Message msg = CoseMessage.DecodeSign1(cborPayload);
+
+ Assert.True(msg.VerifyEmbedded(DefaultKey));
+ }
+
+ [Fact]
+ public void DecodeSign1_IndefiniteLengthArray_MissingBreak()
+ {
+ byte[] cborPayload = ByteUtils.HexToByteArray("D29F43A10126A10442313154546869732069732074686520636F6E74656E742E58408EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36");
+ CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeSign1(cborPayload));
+ Assert.IsType<CborContentException>(ex.InnerException);
+ }
+
+ [Fact]
+ public void DecodeSign1_IndefiniteLengthArray_LargerByOne()
+ {
+ byte[] cborPayload = ByteUtils.HexToByteArray("D29F43A10126A10442313154546869732069732074686520636F6E74656E742E58408EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB3640FF");
+ CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeSign1(cborPayload));
+ Assert.Null(ex.InnerException);
+ }
+
+ [Fact]
+ public void DecodeSign1_IndefiniteLengthArray_ShorterByOne()
+ {
+ byte[] cborPayload = ByteUtils.HexToByteArray("D29F43A10126A10442313154546869732069732074686520636F6E74656E742EFF");
+ CryptographicException ex = Assert.Throws<CryptographicException>(() => CoseMessage.DecodeSign1(cborPayload));
+ Assert.Null(ex.InnerException);
+ }
}
}
MultiSign = 98
}
- internal static void WriteDummyCritHeaderValue(CborWriter writer)
+ internal static void WriteDummyCritHeaderValue(CborWriter writer, bool useIndefiniteLength = false)
{
- writer.WriteStartArray(1);
+ writer.WriteStartArray(useIndefiniteLength ? null : 1);
writer.WriteInt32(42);
writer.WriteEndArray();
}
- internal static byte[] GetDummyCritHeaderValue()
+ internal static byte[] GetDummyCritHeaderValue(bool useIndefiniteLength = false)
{
var writer = new CborWriter();
- WriteDummyCritHeaderValue(writer);
+ WriteDummyCritHeaderValue(writer, useIndefiniteLength);
return writer.Encode();
}