Skip to content

Commit

Permalink
Update to use map rather than root elements and to support named prop…
Browse files Browse the repository at this point in the history
…erties to remove any structure order compatibility issues.
  • Loading branch information
Jstatia committed Feb 23, 2024
1 parent 0d1c167 commit 78a24c4
Showing 1 changed file with 58 additions and 27 deletions.
85 changes: 58 additions & 27 deletions CoseIndirectSignature/CoseHashV.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,19 +239,36 @@ private bool HashMatches(byte[]? data, Stream? stream)
/// <returns>a byte[] cbor representation of the CoseHashV object.</returns>
public byte[] Serialize()
{
CborWriter writer = new(CborConformanceMode.Strict, allowMultipleRootLevelValues: true);
CborWriter writer = new(CborConformanceMode.Strict);

writer.Reset();
int propertyCount = 2;

if(Any != null)
{
propertyCount++;
}

if(Location != null)
{
propertyCount++;
}

writer.WriteStartMap(propertyCount);
writer.WriteTextString("hashAlg");
writer.WriteInt64((long)Algorithm);
writer.WriteTextString("hashValue");
writer.WriteByteString(HashValue);
if (Location != null)
{
writer.WriteTextString("location");
writer.WriteTextString(Location);
}
if (Any != null)
{
writer.WriteTextString("any");
writer.WriteByteString(Any);
}
writer.WriteEndMap();

return writer.Encode();
}
Expand All @@ -262,7 +279,7 @@ public byte[] Serialize()
/// <param name="data">A byte[] which represents a CoseHashV object.</param>
/// <returns>A proper COSE_Hash_V structure if read from the reader.</returns>
/// <exception cref="CoseSign1Exception">Thrown if an invalid object state or format is detected.</exception>
public static CoseHashV Deserialize(byte[] data) => Deserialize(new CborReader(data, allowMultipleRootLevelValues: true));
public static CoseHashV Deserialize(byte[] data) => Deserialize(new CborReader(data));

/// <summary>
/// Reads a COSE_Hash_V structure from the <see cref="CborReader"/>.
Expand All @@ -279,35 +296,49 @@ public static CoseHashV Deserialize(CborReader reader)
}
CoseHashV returnValue = new CoseHashV();

// CBor encodes positive or negative, so we need to check for both.
if (reader.PeekState() != CborReaderState.UnsignedInteger &&
reader.PeekState() != CborReaderState.NegativeInteger)
if (reader.PeekState() != CborReaderState.StartMap)
{
throw new CoseSign1Exception($"Invalid COSE_Hash_V structure, peek state {reader.PeekState()} was not {nameof(CborReaderState.NegativeInteger)} or {nameof(CborReaderState.UnsignedInteger)}");
throw new CoseSign1Exception($"Invalid COSE_Hash_V structure, expected {nameof(CborReaderState.StartMap)} but got {reader.PeekState()} instead.");
}
reader.ReadStartMap();

// read the hash algorithm.
returnValue.Algorithm = (CoseHashAlgorithm)reader.ReadInt64();

// read the hash value
if(reader.PeekState() != CborReaderState.ByteString)
while(!(reader.PeekState() == CborReaderState.EndMap))

Check notice

Code scanning / CodeQL

Unnecessarily complex Boolean expression Note

The expression '!(A == B)' can be simplified to 'A != B'.
{
throw new CoseSign1Exception($"Invalid COSE_Hash_V structure, expected {nameof(CborReaderState.ByteString)} but got {reader.PeekState()} instead.");
}
returnValue.HashValue = reader.ReadByteString();

// read the location if it exists
if (reader.PeekState() == CborReaderState.TextString)
{
returnValue.Location = reader.ReadTextString();
}

// read the any field if it exists
if (reader.PeekState() == CborReaderState.ByteString)
{
returnValue.Any = reader.ReadByteString();
// read the key
string key = reader.ReadTextString();
switch (key.ToLowerInvariant())
{
case "hashalg":
CborReaderState state = reader.PeekState();
if (state != CborReaderState.UnsignedInteger &&
state != CborReaderState.NegativeInteger &&
state != CborReaderState.TextString)
{
throw new CoseSign1Exception($"Invalid COSE_Hash_V structure, expected {nameof(CborReaderState.UnsignedInteger)} or {nameof(CborReaderState.NegativeInteger)} or {nameof(CborReaderState.TextString)} but got {state} instead for \"hashAlg\" property.");
}
if (state == CborReaderState.TextString)
{
returnValue.Algorithm = (CoseHashAlgorithm)Enum.Parse(typeof(CoseHashAlgorithm), reader.ReadTextString(), true);
}
else
{
returnValue.Algorithm = (CoseHashAlgorithm)reader.ReadInt64();
}

Check notice

Code scanning / CodeQL

Missed ternary opportunity Note

Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better.
break;
case "hashvalue":
returnValue.HashValue = reader.ReadByteString();
break;
case "location":
returnValue.Location = reader.ReadTextString();
break;
case "any":
returnValue.Any = reader.ReadByteString();
break;
default:
throw new CoseSign1Exception($"Invalid COSE_Hash_V structure, unexpected key {key} found.");
}
}

reader.ReadEndMap();
return returnValue;
}

Expand Down

0 comments on commit 78a24c4

Please sign in to comment.