public static void DoTestString(String value) { String b = DataUtilities.GetUtf8Length(value, false) + ":" + value; CBORObject beo = EncodingFromBytes(DataUtilities.GetUtf8Bytes(b, false)); Assert.AreEqual(value, beo.AsString()); String newb = DataUtilities.GetUtf8String(EncodingToBytes(beo), false); Assert.AreEqual(b, newb); }
public X9ECParameters GetCurve() { CBORObject cborKeyType = m_map[CoseKeyKeys.KeyType]; if (cborKeyType == null) { throw new CoseException("Malformed key struture"); } if ((cborKeyType.Type != CBORType.Number) && !((cborKeyType == GeneralValues.KeyType_EC) || (cborKeyType == GeneralValues.KeyType_OKP))) { throw new CoseException("Not an EC key"); } CBORObject cborCurve = m_map[CoseKeyParameterKeys.EC_Curve]; if (cborCurve.Type == CBORType.Number) { switch ((GeneralValuesInt)cborCurve.AsInt32()) { case GeneralValuesInt.P256: return(NistNamedCurves.GetByName("P-256")); case GeneralValuesInt.P384: return(NistNamedCurves.GetByName("P-384")); case GeneralValuesInt.P521: return(NistNamedCurves.GetByName("P-521")); case GeneralValuesInt.X25519: return(CustomNamedCurves.GetByName("CURVE25519")); default: throw new CoseException("Unsupported key type: " + cborKeyType.AsInt32()); } } else if (cborCurve.Type == CBORType.TextString) { switch (cborCurve.AsString()) { default: throw new CoseException("Unsupported key type: " + cborKeyType.AsString()); } } else { throw new CoseException("Incorrectly encoded key type"); } }
public void AddKey() { CBORObject result = _dictionary.Lookup("missing", false); Assert.AreEqual("missing", result.AsString()); _dictionary.Add(7, "missing"); result = _dictionary.Lookup("missing", false); Assert.AreEqual(7, result.AsInt32()); Cori cori = new Cori("coap://host2:99/path1/path2/path4"); _dictionary.Add(8, cori); Cori ciri2 = new Cori(cori.ToString()); result = _dictionary.Lookup(ciri2, false); Assert.AreEqual(8, result.AsInt32()); _dictionary.Add(9, new Cori(CBORObject.DecodeFromBytes(Hex.Decode("8405000664666F726D")))); Assert.ThrowsException <ArgumentException>(() => _dictionary.Add(10, CBORObject.FromObject(DateTime.UtcNow))); }
public CBORObject Lookup(CBORObject value, bool isIntLegal) { if (value.Type == CBORType.TextString) { return(Lookup(value.AsString(), isIntLegal)); } foreach (KeyValuePair <int, object> o in _dictionary) { if (value.Equals(o.Value)) { if (isIntLegal) { return(CBORObject.FromObjectAndTag(o.Key, DictionaryTag)); } return(CBORObject.FromObject(o.Key)); } } return(value); }
public CoralDictionary Add(int key, CBORObject value) { if (key < 0) { throw new ArgumentException("Key must be a non-negative value", nameof(key)); } if (!CoralItem.IsLiteral(value)) { throw new ArgumentException("Value must be a literal value"); } if (value.Type == CBORType.TextString) { _dictionary.Add(key, value.AsString()); } else { _dictionary.Add(key, value); } return(this); }
public static byte[] Sign(byte[] toBeSigned, CBORObject alg, OneKey keyToSign) { IDigest digest = null; IDigest digest2 = null; if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "PS384": digest = new Sha384Digest(); digest2 = new Sha384Digest(); break; case "HSS-LMS": break; default: throw new Exception("Unknown signature algorithm"); } } else if (alg.Type == CBORType.Integer) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.ECDSA_256: case AlgorithmValuesInt.RSA_PSS_256: digest = new Sha256Digest(); digest2 = new Sha256Digest(); break; case AlgorithmValuesInt.ECDSA_384: case AlgorithmValuesInt.RSA_PSS_384: digest = new Sha384Digest(); digest2 = new Sha384Digest(); break; case AlgorithmValuesInt.ECDSA_512: case AlgorithmValuesInt.RSA_PSS_512: digest = new Sha512Digest(); digest2 = new Sha512Digest(); break; case AlgorithmValuesInt.EdDSA: break; default: throw new CoseException("Unknown signature algorithm"); } } else { throw new CoseException("Algorithm incorrectly encoded"); } if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "HSS-LMS": HashSig sig = new HashSig(keyToSign[CoseKeyParameterKeys.Lms_Private].AsString()); byte[] signBytes = sig.Sign(toBeSigned); keyToSign.Replace(CoseKeyParameterKeys.Lms_Private, CBORObject.FromObject(sig.PrivateKey)); return(signBytes); default: throw new CoseException("Unknown Algorithm"); } } else if (alg.Type == CBORType.Integer) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.RSA_PSS_256: case AlgorithmValuesInt.RSA_PSS_384: case AlgorithmValuesInt.RSA_PSS_512: { PssSigner signer = new PssSigner(new RsaEngine(), digest, digest2, digest.GetDigestSize()); ICipherParameters prv = keyToSign.AsPrivateKey(); ParametersWithRandom param = new ParametersWithRandom(prv, Message.GetPRNG()); signer.Init(true, param); signer.BlockUpdate(toBeSigned, 0, toBeSigned.Length); return(signer.GenerateSignature()); } case AlgorithmValuesInt.ECDSA_256: case AlgorithmValuesInt.ECDSA_384: case AlgorithmValuesInt.ECDSA_512: { SecureRandom random = Message.GetPRNG(); digest.BlockUpdate(toBeSigned, 0, toBeSigned.Length); byte[] digestedMessage = new byte[digest.GetDigestSize()]; digest.DoFinal(digestedMessage, 0); ICipherParameters privKey = keyToSign.AsPrivateKey(); X9ECParameters p = keyToSign.GetCurve(); ParametersWithRandom param = new ParametersWithRandom(privKey, random); ECDsaSigner ecdsa = new ECDsaSigner(new HMacDsaKCalculator(new Sha256Digest())); ecdsa.Init(true, param); BigInteger[] sig = ecdsa.GenerateSignature(digestedMessage); byte[] r = sig[0].ToByteArrayUnsigned(); byte[] s = sig[1].ToByteArrayUnsigned(); int cbR = (p.Curve.FieldSize + 7) / 8; byte[] sigs = new byte[cbR * 2]; Array.Copy(r, 0, sigs, cbR - r.Length, r.Length); Array.Copy(s, 0, sigs, cbR + cbR - s.Length, s.Length); return(sigs); } case AlgorithmValuesInt.EdDSA: { ISigner eddsa; if (keyToSign[CoseKeyParameterKeys.EC_Curve].Equals(GeneralValues.Ed25519)) { ICipherParameters privKey = keyToSign.AsPrivateKey(); eddsa = new Ed25519Signer(); eddsa.Init(true, privKey); } else if (keyToSign[CoseKeyParameterKeys.EC_Curve].Equals(GeneralValues.Ed448)) { ICipherParameters privKey = keyToSign.AsPrivateKey(); eddsa = new Ed448Signer(new byte[0]); eddsa.Init(true, privKey); } else { throw new CoseException("Unrecognized curve"); } eddsa.BlockUpdate(toBeSigned, 0, toBeSigned.Length); return(eddsa.GenerateSignature()); } default: throw new CoseException("Unknown Algorithm"); } } else { throw new CoseException("Algorithm incorrectly encoded"); } }
protected byte[] HMAC(CBORObject alg, byte[] K) { int cbitKey; int cbResult; IDigest digest; if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { default: throw new Exception("Unrecognized algorithm"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.HMAC_SHA_256: cbitKey = 256; cbResult = 256 / 8; digest = new Sha256Digest(); break; case AlgorithmValuesInt.HMAC_SHA_256_64: cbitKey = 256; digest = new Sha256Digest(); cbResult = 64 / 8; break; case AlgorithmValuesInt.HMAC_SHA_384: cbitKey = 384; digest = new Sha384Digest(); cbResult = cbitKey / 8; break; case AlgorithmValuesInt.HMAC_SHA_512: cbitKey = 512; digest = new Sha512Digest(); cbResult = cbitKey / 8; break; default: throw new CoseException("Unknown or unsupported algorithm"); } } else { throw new CoseException("Algorithm incorrectly encoded"); } if (K == null) { throw new CoseException("No Key value"); } HMac hmac = new HMac(digest); KeyParameter key = new KeyParameter(K); byte[] resBuf = new byte[hmac.GetMacSize()]; byte[] toDigest = BuildContentBytes(); hmac.Init(key); hmac.BlockUpdate(toDigest, 0, toDigest.Length); hmac.DoFinal(resBuf, 0); byte[] rgbOut = new byte[cbResult]; Array.Copy(resBuf, rgbOut, cbResult); return(rgbOut); }
public bool Validate(Key recipientReceiver) { byte[] rgbKey = null; int cbitKey; if (recipientReceiver[CoseKeyKeys.KeyType].AsInt32() != (int)GeneralValuesInt.KeyType_Octet) { throw new CoseException("Key type not octet"); } rgbKey = recipientReceiver[CoseKeyParameterKeys.Octet_k].GetByteString(); CBORObject alg = FindAttribute(COSE.HeaderKeys.Algorithm); if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "AES-CMAC-128/64": cbitKey = 128; break; case "AES-CMAC-256/64": cbitKey = 256; break; default: throw new Exception("MAC algorithm is not recognized"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.HMAC_SHA_256_64: case AlgorithmValuesInt.HMAC_SHA_256: cbitKey = 256; break; case AlgorithmValuesInt.HMAC_SHA_384: cbitKey = 384; break; case AlgorithmValuesInt.HMAC_SHA_512: cbitKey = 512; break; case AlgorithmValuesInt.AES_CBC_MAC_128_64: case AlgorithmValuesInt.AES_CBC_MAC_128_128: cbitKey = 128; break; case AlgorithmValuesInt.AES_CBC_MAC_256_64: case AlgorithmValuesInt.AES_CBC_MAC_256_128: cbitKey = 256; break; default: throw new Exception("MAC algorithm not recognized" + alg.AsInt32()); } } else { throw new CoseException("Algorithm incorrectly encoded"); } if (rgbKey == null) { throw new CoseException("No Key Provided"); } byte[] rgbCheck; if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "AES-CMAC-128/64": case "AES-CMAC-256/64": rgbCheck = AES_CMAC(alg, rgbKey); break; default: throw new Exception("MAC algorithm is not recognized"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.HMAC_SHA_256: case AlgorithmValuesInt.HMAC_SHA_384: case AlgorithmValuesInt.HMAC_SHA_512: case AlgorithmValuesInt.HMAC_SHA_256_64: rgbCheck = HMAC(alg, rgbKey); break; case AlgorithmValuesInt.AES_CBC_MAC_128_64: case AlgorithmValuesInt.AES_CBC_MAC_128_128: case AlgorithmValuesInt.AES_CBC_MAC_256_64: case AlgorithmValuesInt.AES_CBC_MAC_256_128: rgbCheck = AES_CBC_MAC(alg, rgbKey); break; default: throw new Exception("MAC algorithm not recognized" + alg.AsInt32()); } } else { throw new CoseException("Algorithm incorrectly encoded"); } bool fReturn = true; for (int i = 0; i < rgbCheck.Length; i++) { fReturn &= (rgbTag[i] == rgbCheck[i]); } return(fReturn); }
public bool Validate(byte[] content, byte[] msgAttributes) { CBORObject alg = null; // Get the set algorithm or infer one byte[] bytesToBeSigned = toBeSigned(content, msgAttributes); alg = FindAttribute(HeaderKeys.Algorithm); if (alg == null) { throw new Exception("No Signature algorithm known"); } IDigest digest; IDigest digest2; if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "PS384": digest = new Sha384Digest(); digest2 = new Sha384Digest(); break; default: throw new Exception("Unknown signature algorithm"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.ECDSA_256: case AlgorithmValuesInt.RSA_PSS_256: digest = new Sha256Digest(); digest2 = new Sha256Digest(); break; case AlgorithmValuesInt.ECDSA_384: case AlgorithmValuesInt.RSA_PSS_384: digest = new Sha384Digest(); digest2 = new Sha384Digest(); break; case AlgorithmValuesInt.ECDSA_512: case AlgorithmValuesInt.RSA_PSS_512: digest = new Sha512Digest(); digest2 = new Sha512Digest(); break; default: throw new CoseException("Unknown signature algorith"); } } else { throw new CoseException("Algorthm incorrectly encoded"); } if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "PS384": { PssSigner signer = new PssSigner(new RsaEngine(), digest, digest2, digest.GetByteLength()); RsaKeyParameters prv = new RsaPrivateCrtKeyParameters(keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_n), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_e), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_d), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_p), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_q), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_dP), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_dQ), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_qInv)); ParametersWithRandom param = new ParametersWithRandom(prv, Message.GetPRNG()); signer.Init(true, param); signer.BlockUpdate(bytesToBeSigned, 0, bytesToBeSigned.Length); return(signer.VerifySignature(rgbSignature)); } default: throw new CoseException("Unknown Algorithm"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.RSA_PSS_256: case AlgorithmValuesInt.RSA_PSS_512: { PssSigner signer = new PssSigner(new RsaEngine(), digest, digest2, digest.GetByteLength()); RsaKeyParameters prv = new RsaPrivateCrtKeyParameters(keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_n), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_e), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_d), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_p), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_q), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_dP), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_dQ), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_qInv)); ParametersWithRandom param = new ParametersWithRandom(prv, Message.GetPRNG()); signer.Init(true, param); signer.BlockUpdate(bytesToBeSigned, 0, bytesToBeSigned.Length); return(signer.VerifySignature(rgbSignature)); } case AlgorithmValuesInt.ECDSA_256: case AlgorithmValuesInt.ECDSA_384: case AlgorithmValuesInt.ECDSA_512: { digest.BlockUpdate(bytesToBeSigned, 0, bytesToBeSigned.Length); byte[] digestedMessage = new byte[digest.GetDigestSize()]; digest.DoFinal(digestedMessage, 0); X9ECParameters p = keyToSign.GetCurve(); ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); ECPoint point = keyToSign.GetPoint(); ECPublicKeyParameters param = new ECPublicKeyParameters(point, parameters); ECDsaSigner ecdsa = new ECDsaSigner(); ecdsa.Init(false, param); BigInteger r = new BigInteger(1, rgbSignature, 0, rgbSignature.Length / 2); BigInteger s = new BigInteger(1, rgbSignature, rgbSignature.Length / 2, rgbSignature.Length / 2); return(ecdsa.VerifySignature(digestedMessage, r, s)); } default: throw new CoseException("Unknown Algorithm"); } } else { throw new CoseException("Algorithm incorrectly encoded"); } }
private static RemoteResource DeserializeCbor(CBORObject cbor) { if (cbor.Type != CBORType.Array) { throw new ArgumentException(); } RemoteResource root = new RemoteResource(string.Empty); for (int i = 0; i < cbor.Count; i++) { string href; if (cbor[i].ContainsKey("href")) { href = cbor[i]["href"].AsString(); } else { href = cbor[i][CBORObject.FromObject(1)].AsString(); } RemoteResource child = new RemoteResource(href); foreach (CBORObject key in cbor[i].Keys) { string keyName; if (key.Type == CBORType.Number) { keyName = null; foreach (KeyValuePair <string, CBORObject> kvp in _CborAttributeKeys) { if (key.Equals(kvp.Value)) { keyName = kvp.Key; break; } } if (keyName == null) { throw new ArgumentException("Invalid numeric key"); } } else if (key.Type == CBORType.TextString) { keyName = key.AsString(); } else { throw new ArgumentException("Unexpected key type found"); } if (keyName == "href") { continue; } CBORObject value = cbor[i][key]; if (value.Type == CBORType.TextString) { child.Attributes.Add(keyName, value.AsString()); } else if (value.Type == CBORType.Boolean) { child.Attributes.Add(keyName); } else if (value.Type == CBORType.Array) { for (int i1 = 0; i1 < value.Count; i1++) { if (value[i1].Type == CBORType.TextString) { child.Attributes.Add(keyName, value[i1].AsString()); } else if (value[i1].Type == CBORType.Boolean) { if (value[i1].AsBoolean() != true) { throw new ArgumentException("false unexpectedly found"); } child.Attributes.Add(keyName); } else { throw new ArgumentException("Unexpected value type found"); } } } else { throw new ArgumentException("Unexpected value type found"); } } root.AddSubResource(child); } return(root); }
/// <summary> /// Compute and derive the keys based on the input data /// </summary> /// <param name="keys">Public and Private DH keys to use for creating shared secret</param> /// <param name="salt">A shared symmetric key if one exists</param> /// <param name="otherData">SuppPubInfo other data bytes - changes for each message</param> /// <param name="algAEAD">Symmetric algorithm for encryption</param> /// <returns>array of two byte arrays. The first is the key, the second is the IV</returns> protected static byte[][] _DeriveKeys(OneKey[] keys, byte[] salt, byte[] otherData, CBORObject algAEAD) { int cbitKey = 0; int cbitIV = 0; byte[] secret = ECDH_GenerateSecret(keys); if (algAEAD.Type == CBORType.Number) { switch ((AlgorithmValuesInt)algAEAD.AsInt32()) { case AlgorithmValuesInt.AES_CCM_64_64_128: cbitKey = 128; cbitIV = 58; break; default: throw new Exception("Unknown Algorithm"); } } else if (algAEAD.Type == CBORType.TextString) { switch (algAEAD.AsString()) { case "EDHOC OSCOAP Master Secret": cbitKey = 128; break; case "EDHOC OSCOAP Master Salt": cbitKey = 64; break; default: throw new Exception("Unknown Algorithm"); } } else { throw new Exception("Internal Error"); } CBORObject partyInfo; partyInfo = CBORObject.NewArray(); partyInfo.Add(CBORObject.Null); partyInfo.Add(CBORObject.Null); partyInfo.Add(CBORObject.Null); CBORObject context = CBORObject.NewArray(); context.Add(algAEAD); // Alg context.Add(partyInfo); // Party U context.Add(partyInfo); // Party V CBORObject obj = CBORObject.NewArray(); obj.Add(cbitKey / 8); obj.Add(CBORObject.FromObject(new byte[0])); obj.Add(otherData); context.Add(obj); // SuppPubInfo byte[] rgbContext = context.EncodeToBytes(); byte[][] returnValue = new byte[2][]; returnValue[0] = HKDF(secret, salt, rgbContext, cbitKey, new Sha256Digest()); if (cbitIV > 0) { obj[0] = CBORObject.FromObject(cbitIV / 8); context[0] = CBORObject.FromObject("IV-GENERATION"); returnValue[1] = HKDF(secret, salt, rgbContext, cbitIV, new Sha256Digest()); } return(returnValue); }
static bool ValidateEnveloped(CBORObject control) { CBORObject input = control["input"]; CBORObject encrypt = input["enveloped"]; if ((!encrypt.ContainsKey("recipients")) || (encrypt["recipients"].Type != CBORType.Array)) { throw new Exception("Missing or malformed recipients"); } for (int iRecipient = 0; iRecipient < encrypt["recipients"].Count; iRecipient++) { bool fFail = HasFailMarker(control) || HasFailMarker(encrypt); EncryptMessage encryptMessage; try { Message message; CBORObject obj = control["output"]["json"]; if (obj.Type == CBORType.TextString) { message = Message.DecodeFromString(obj.AsString()); } else { message = Message.DecodeFromJSON(obj); } encryptMessage = (EncryptMessage)message; } catch (Exception) { if (fFail) { return(true); } return(false); } if (encrypt.ContainsKey("unsent")) { AddAttributes(encryptMessage, encrypt["unsent"], 2); } CBORObject recipient = encrypt["recipients"][iRecipient]; Recipient recipientMessage = encryptMessage.RecipientList[iRecipient]; recipientMessage = SetReceivingAttributes(recipientMessage, recipient); /* * if (recipient["sender_key"] != null) * { * if (recipientMessage.FindAttribute(HeaderKeys.StaticKey) == null) * { * recipientMessage.AddAttribute(HeaderKeys.StaticKey, GetKey(recipient["sender_key"], true).AsCBOR(), * Attributes.DO_NOT_SEND); * } * } */ bool fFailRecipient = HasFailMarker(recipient); try { encryptMessage.Decrypt(recipientMessage); if (encryptMessage.GetContentAsString() != input["plaintext"].AsString()) { return(false); } } catch (Exception) { if (fFail || fFailRecipient) { return(true); } return(false); } } return(true); }
static bool ProcessJSON(CBORObject control) { bool modified = false; StaticPrng prng = new StaticPrng(); if (control.ContainsKey("title")) { Console.Write("Processing: " + control["title"].AsString()); } if (control["input"].ContainsKey("rng_stream")) { if (control["input"]["rng_stream"].Type == CBORType.TextString) { prng.AddSeedMaterial(Program.FromHex(control["input"]["rng_stream"].AsString())); } else if (control["input"]["rng_stream"].Type == CBORType.Array) { foreach (var x in control["input"]["rng_stream"].Values) { prng.AddSeedMaterial(Program.FromHex(x.AsString())); } } } Message.SetPRNG(prng); try { prng.Reset(); Message result; if (control["input"].ContainsKey("enveloped")) { result = ProcessEnveloped(control, ref modified); } else if (control["input"].ContainsKey("sign")) { result = ProcessSign(control, ref modified); } else { throw new Exception("Unknown operation in control"); } foreach (string format in Formats) { CBORObject json = null; string jsonText = null; try { switch (format) { case "json": json = result.EncodeToJSON(false); break; case "json_flat": json = result.EncodeToJSON(true); break; case "compact": jsonText = result.EncodeCompressed(); break; } } catch (JoseException) { // Ignore } if (control["output"].ContainsKey(format)) { if (json == null && jsonText == null) { control["output"].Remove(format); modified = true; } else { CBORObject oldVersion = control["output"][format]; if (format == "compact") { if (oldVersion.Type != CBORType.TextString || jsonText != oldVersion.AsString()) { Console.WriteLine(); Console.WriteLine($"******************* New and Old do not match {format}!!!"); Console.WriteLine(); control["output"][format] = CBORObject.FromObject(jsonText); modified = true; } } else if (json.ToJSONString() != oldVersion.ToJSONString()) { Console.WriteLine(); Console.WriteLine($"******************* New and Old do not match {format}!!!"); Console.WriteLine(); control["output"][format] = json; modified = true; } } } else { if (format == "compact" && jsonText != null) { control["output"].Add(format, jsonText); modified = true; } else if (json != null) { control["output"].Add(format, json); modified = true; } } } if (prng.IsDirty) { if (prng.Buffer != null) { if (control["input"].ContainsKey("rng_stream")) { control["input"]["rng_stream"] = prng.Buffer; } else { control["input"].Add("rng_stream", prng.Buffer); } } else { if (control["input"].ContainsKey("rng_stream")) { control["input"].Remove(CBORObject.FromObject("rng_stream")); } } modified = true; } } catch (Com.AugustCellars.JOSE.JoseException e) { Console.WriteLine($"JOSE threw an error '{e}'."); } return(modified); }
void ProcessFile(FileInfo testCase) { if (testCase.Extension != ".json") { return; } if (testCase.Name[0] == '.') { return; } Debug.Print($"Working on file {testCase}"); Console.WriteLine("Working on file '" + testCase + "'"); string inputText = testCase.OpenText().ReadToEnd(); CBORObject test = CBORObject.FromJSONString(inputText); KeySet decodeKeys = new KeySet(); KeySet signKeys = new KeySet(); CBORObject input = test["input"]; CWT cwt = new CWT(); if (input.ContainsKey("encrypted")) { OneKey key = LoadKey(input["encrypted"]["key"]); cwt.EncryptionKey = key; decodeKeys.AddKey(key); } if (input.ContainsKey("mac0")) { OneKey key = LoadKey(input["mac0"]["key"]); cwt.MacKey = key; decodeKeys.AddKey(key); } if (input.ContainsKey("sign0")) { OneKey key = LoadKey(input["sign0"]["key"]); cwt.SigningKey = key; signKeys.AddKey(key.PublicKey()); } CWT cwt2 = CWT.Decode(FromHex(test["output"]["cbor"].AsString()), decodeKeys, signKeys); CBORObject token = input["token"]; foreach (CBORObject key in token.Keys) { CBORObject value = token[key]; CBORObject key2 = key; if (key.AsString().EndsWith("_hex")) { value = CBORObject.FromObject(FromHex(value.AsString())); key2 = CBORObject.FromObject(key.AsString().Substring(0, key.AsString().Length - 4)); } cwt.SetClaim(key2, value); Assert.True(cwt2.HasClaim(key2), $"Missing Claim {key2}"); Assert.AreEqual(value, cwt.GetClaim(key2)); } byte[] foo = cwt.EncodeToBytes(); cwt2 = CWT.Decode(foo, decodeKeys, signKeys); foreach (CBORObject key in token.Keys) { CBORObject value = token[key]; CBORObject key2 = key; if (key.AsString().EndsWith("_hex")) { value = CBORObject.FromObject(FromHex(value.AsString())); key2 = CBORObject.FromObject(key.AsString().Substring(0, key.AsString().Length - 4)); } Assert.True(cwt2.HasClaim(key2)); Assert.AreEqual(value, cwt.GetClaim(key2)); } }
OneKey LoadKey(CBORObject obj) { OneKey newKey = new OneKey(); CBORObject kty; switch (obj["kty"].AsString()) { case "oct": kty = GeneralValues.KeyType_Octet; break; case "EC": kty = GeneralValues.KeyType_EC; break; default: throw new Exception("Unknown key type " + obj["cty"].AsString()); } foreach (CBORObject key in obj.Keys) { CBORObject value = obj[key]; CBORObject key2 = key; if (key.AsString().EndsWith("_hex")) { value = CBORObject.FromObject(FromHex(value.AsString())); key2 = CBORObject.FromObject(key.AsString().Substring(0, key.AsString().Length - 4)); } key2 = MapKey(key2); if (key2.Equals(CoseKeyKeys.KeyType)) { value = kty; } else if (key2.Equals(CoseKeyKeys.KeyIdentifier)) { value = CBORObject.FromObject(Encoding.UTF8.GetBytes(value.AsString())); } else if (key2.Equals(CoseKeyKeys.Algorithm)) { value = MapAlgorithm(value.AsString()); } else if (kty.Equals(GeneralValues.KeyType_EC) && key2.Equals(CoseKeyParameterKeys.EC_Curve)) { switch (value.AsString()) { case "P-256": value = GeneralValues.P256; break; default: throw new Exception("Unknown curve " + value.AsString()); } } newKey.Add(key2, value); } return(newKey); }
public static bool Validate(byte[] content, CBORObject alg, OneKey signKey, byte[] rgbSignature) { IDigest digest = null; IDigest digest2 = null; if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "HSS-LMS": break; default: throw new Exception("Unknown signature algorithm"); } } else if (alg.Type == CBORType.Integer) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.ECDSA_256: case AlgorithmValuesInt.RSA_PSS_256: digest = new Sha256Digest(); digest2 = new Sha256Digest(); break; case AlgorithmValuesInt.ECDSA_384: case AlgorithmValuesInt.RSA_PSS_384: digest = new Sha384Digest(); digest2 = new Sha384Digest(); break; case AlgorithmValuesInt.ECDSA_512: case AlgorithmValuesInt.RSA_PSS_512: digest = new Sha512Digest(); digest2 = new Sha512Digest(); break; case AlgorithmValuesInt.EdDSA: break; default: throw new CoseException("Unknown signature algorith"); } } else { throw new CoseException("Algorithm incorrectly encoded"); } if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "HSS-LMS": return(HashSig.Validate(content, signKey[CoseKeyParameterKeys.Lms_Public].GetByteString(), rgbSignature)); default: throw new CoseException("Unknown Algorithm"); } } else if (alg.Type == CBORType.Integer) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.RSA_PSS_256: case AlgorithmValuesInt.RSA_PSS_384: case AlgorithmValuesInt.RSA_PSS_512: { PssSigner signer = new PssSigner(new RsaEngine(), digest, digest2, digest.GetDigestSize()); ICipherParameters prv = signKey.AsPublicKey(); ParametersWithRandom param = new ParametersWithRandom(prv, Message.GetPRNG()); signer.Init(false, param); signer.BlockUpdate(content, 0, content.Length); return(signer.VerifySignature(rgbSignature)); } case AlgorithmValuesInt.ECDSA_256: case AlgorithmValuesInt.ECDSA_384: case AlgorithmValuesInt.ECDSA_512: { if (signKey.GetKeyType() != GeneralValuesInt.KeyType_EC2) { throw new CoseException("Key is not correctly constructed."); } digest.BlockUpdate(content, 0, content.Length); byte[] digestedMessage = new byte[digest.GetDigestSize()]; digest.DoFinal(digestedMessage, 0); ICipherParameters param = signKey.AsPublicKey(); ECDsaSigner ecdsa = new ECDsaSigner(); ecdsa.Init(false, param); BigInteger r = new BigInteger(1, rgbSignature, 0, rgbSignature.Length / 2); BigInteger s = new BigInteger(1, rgbSignature, rgbSignature.Length / 2, rgbSignature.Length / 2); return(ecdsa.VerifySignature(digestedMessage, r, s)); } #if true case AlgorithmValuesInt.EdDSA: { ISigner eddsa; if (signKey[CoseKeyParameterKeys.EC_Curve].Equals(GeneralValues.Ed25519)) { ICipherParameters privKey = signKey.AsPublicKey(); eddsa = new Ed25519Signer(); eddsa.Init(false, privKey); } else if (signKey[CoseKeyParameterKeys.EC_Curve].Equals(GeneralValues.Ed448)) { Ed448PublicKeyParameters privKey = new Ed448PublicKeyParameters(signKey[CoseKeyParameterKeys.OKP_X].GetByteString(), 0); eddsa = new Ed448Signer(new byte[0]); eddsa.Init(false, privKey); } else { throw new CoseException("Unrecognized curve"); } eddsa.BlockUpdate(content, 0, content.Length); return(eddsa.VerifySignature(rgbSignature)); } #endif default: throw new CoseException("Unknown Algorithm"); } } else { throw new CoseException("Algorithm incorrectly encoded"); } }
/// <summary> /// Encrypt the message based on attributes and recipients. /// </summary> public virtual void Encrypt() { string alg = null; // Get the algorithm we are using - the default is AES GCM try { alg = FindAttribute("enc").AsString(); } catch { foreach (Recipient r in RecipientList) { CBORObject alg2 = r.FindAttribute("enc"); if (alg2 != null) { if (alg2.Type != CBORType.TextString || (alg != null && alg != alg2.AsString())) { throw new JoseException("Multiple content encryption algorithms have been specified."); } alg = alg2.AsString(); } } if (alg == null) { throw new JoseException("Content encryption algorithm has not been specified."); } } byte[] contentKey = null; // Determine if we are doing a direct encryption int recipientTypes = 0; if (RecipientList.Count == 0) { throw new JoseException("Must have at least one recipient for the message"); } foreach (Recipient key in RecipientList) { switch (key.RecipientType) { case RecipientType.Direct: case RecipientType.KeyAgreeDirect: if ((recipientTypes & 1) != 0) { throw new JoseException("It is not legal to have two direct recipients in a message"); } recipientTypes |= 1; contentKey = key.GetKey(alg, this); break; default: recipientTypes |= 2; break; } } if (recipientTypes == 3) { throw new JoseException("It is not legal to mix direct and indirect recipients in a message"); } if (contentKey == null) { switch (alg) { case "A128GCM": case "AES-128-CCM-64": contentKey = new byte[128 / 8]; break; case "A192GCM": case "AES192GCM": contentKey = new byte[192 / 8]; break; case "A256GCM": case "AES256GCM": contentKey = new byte[256 / 8]; break; case "A128CBC-HS256": contentKey = new byte[2 * 128 / 8]; break; case "A192CBC-HS256": contentKey = new byte[2 * 192 / 8]; break; case "A256CBC-HS256": contentKey = new byte[2 * 256 / 8]; break; default: throw new JoseException($"Unrecognized content encryption algorithm '{alg}'"); } s_PRNG.NextBytes(contentKey); } foreach (Recipient key in RecipientList) { key.SetContent(contentKey); key.Encrypt(this); } // Encode the protected attributes if there are any if (ProtectedMap.Count > 0) { _strProtected = base64urlencode(Encoding.UTF8.GetBytes(ProtectedMap.ToString())); } byte[] saveContent = payload; if (ProtectedMap.ContainsKey("zip")) { MemoryStream stm2 = new MemoryStream(); DeflateStream zipStm = new DeflateStream(stm2, CompressionMode.Compress); zipStm.Write(payload, 0, payload.Length); zipStm.Close(); payload = stm2.GetBuffer(); } switch (alg) { case "A128GCM": case "A192GCM": case "A256GCM": AES_GCM_Encrypt(contentKey); break; case "AES-128-CCM-64": AES_CCM(contentKey); break; case "A128CBC-HS256": case "A192CBC-HS256": case "A256CBC-HS256": AES_CBC_MAC_Encrypt(alg, contentKey); break; default: throw new JoseException("Internal Error: We should never get here."); } payload = saveContent; }
static void _AddAttributes(Attributes msg, CBORObject map, CBORObject items, int destination) { foreach (CBORObject cborKey2 in items.Keys) { CBORObject cborValue = items[cborKey2]; CBORObject cborKey = cborKey2; string strKey = cborKey.AsString(); if ((strKey.Length > 4) && (strKey.Substring(strKey.Length - 4, 4) == "_hex")) { cborKey = CBORObject.FromObject(strKey.Substring(0, strKey.Length - 4)); cborValue = CBORObject.FromObject(FromHex(cborValue.AsString())); } if (cborKey.AsString() == "comment") { continue; } switch (cborKey.AsString()) { case "alg": break; case "kid": binFromText: break; case "epk": break; case "spk": break; case "salt": goto binFromText; case "apu_id": goto binFromText; case "apv_id": goto binFromText; case "apu_nonce": goto binFromText; case "apv_nonce": goto binFromText; case "apu_other": goto binFromText; case "apv_other": goto binFromText; case "pub_other": goto binFromText; case "priv_other": goto binFromText; case "spk_kid": goto binFromText; case "IV": goto binFromText; case "partialIV": goto binFromText; case "crit": break; case "op time": { DateTime when = DateTime.Parse(cborValue.AsString()); cborValue = CBORObject.FromObject( (long)(when - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds); } break; case "ctyp": break; case "x5u": break; case "x5u-sender": break; default: break; } switch (destination) { case 0: msg.AddAttribute(cborKey, cborValue, Attributes.PROTECTED); break; case 1: msg.AddAttribute(cborKey, cborValue, Attributes.UNPROTECTED); break; case 2: msg.AddAttribute(cborKey, cborValue, Attributes.DO_NOT_SEND); break; case 4: map[cborKey] = cborValue; break; } } }
private static IEnumerable <WebLink> ParseCommon(CBORObject links, Dictionary <string, CBORObject> dictionary) { if (links.Type != CBORType.Array) { throw new ArgumentException("Not an array"); } for (int i = 0; i < links.Count; i++) { CBORObject resource = links[i]; if (resource.Type != CBORType.Map) { throw new ArgumentException("Element not correctly formatted"); } string name; if (resource.ContainsKey("href")) { name = resource["href"].AsString(); } else { name = resource[CBORObject.FromObject(1)].AsString(); } WebLink link = new WebLink(name); foreach (CBORObject key in resource.Keys) { string keyName = null; if (dictionary != null && key.Type == CBORType.Number) { foreach (KeyValuePair <string, CBORObject> kvp in dictionary) { if (key.Equals(kvp.Value)) { keyName = kvp.Key; break; } } } if (keyName == null) { keyName = key.AsString(); } if (ParseStrictMode && SingleOccuranceAttributes.Contains(keyName)) { throw new ArgumentException($"'{keyName}' occurs multiple times"); } CBORObject value = resource[key]; if (value.Type == CBORType.Boolean) { link.Attributes.Add(name); } else if (value.Type == CBORType.TextString) { link.Attributes.Add(name, value.AsString()); } else if (value.Type == CBORType.Array) { for (int i1 = 0; i1 < value.Count; i1++) { if (value.Type == CBORType.Boolean) { link.Attributes.Add(name); } else if (value.Type == CBORType.TextString) { link.Attributes.Add(name, value.AsString()); } else { throw new ArgumentException("incorrect type"); } } } else { throw new ArgumentException("incorrect type"); } } yield return(link); } }
private string _PrintCBOR(CBORObject obj, int iLevel) { string strOut = ""; string strLine; string pad = ((String)" ").Substring(0, iLevel); switch (obj.Type) { case CBORType.Array: strOut = "[\n"; for (int i = 0; i < obj.Count; i++) { strOut += pad + " " + _PrintCBOR(obj[i], iLevel + 1) + ",\n"; } strOut += pad + "]"; break; case CBORType.Map: strOut = "{\n"; foreach (CBORObject key in obj.Keys) { strOut += pad + " " + _PrintCBOR(key, 0) + " : " + _PrintCBOR(obj[key], iLevel + 1) + ",\n"; } strOut += pad + "}"; break; case CBORType.ByteString: strLine = pad + "h'"; byte[] rgb = obj.GetByteString(); byte[] rgb2 = new byte[1]; foreach (byte b in rgb) { if (strLine.Length > 66) { if (strOut == "") { strOut = strLine.Substring(iLevel) + "\n"; } else { strOut += strLine + "\n"; } strLine = pad + " "; } rgb2[0] = b; strLine += BitConverter.ToString(rgb2); } strOut += strLine; strOut += "'"; break; case CBORType.Integer: strOut = obj.AsInt32().ToString(); break; case CBORType.SimpleValue: if (obj.IsNull) { return("null"); } return(obj.Type.ToString()); case CBORType.TextString: strOut = "\"" + obj.AsString() + "\""; break; default: strOut = obj.Type.ToString(); break; } return(strOut); }
private byte[] Sign(byte[] bytesToBeSigned) { CBORObject alg = null; // Get the set algorithm or infer one alg = FindAttribute(HeaderKeys.Algorithm); if (alg == null) { if (keyToSign[CoseKeyKeys.KeyType].Type == CBORType.Number) { switch ((GeneralValuesInt)keyToSign[CoseKeyKeys.KeyType].AsInt32()) { case GeneralValuesInt.KeyType_RSA: alg = CBORObject.FromObject("PS256"); break; case GeneralValuesInt.KeyType_EC2: if (keyToSign[CoseKeyParameterKeys.EC_Curve].Type == CBORType.Number) { switch ((GeneralValuesInt)keyToSign[CoseKeyParameterKeys.EC_Curve].AsInt32()) { case GeneralValuesInt.P256: alg = AlgorithmValues.ECDSA_256; break; case GeneralValuesInt.P384: alg = AlgorithmValues.ECDSA_384; break; case GeneralValuesInt.P521: alg = AlgorithmValues.ECDSA_512; break; default: throw new CoseException("Unknown curve"); } } else if (keyToSign[CoseKeyParameterKeys.EC_Curve].Type == CBORType.TextString) { switch (keyToSign[CoseKeyParameterKeys.EC_Curve].AsString()) { default: throw new CoseException("Unknown curve"); } } else { throw new CoseException("Curve is incorrectly encoded"); } break; default: throw new Exception("Unknown or unsupported key type " + keyToSign.AsString("kty")); } } else if (keyToSign[CoseKeyKeys.KeyType].Type == CBORType.TextString) { throw new CoseException("Unknown or unsupported key type " + keyToSign[CoseKeyKeys.KeyType].AsString()); } else { throw new CoseException("Key type is not correctly encoded"); } objUnprotected.Add(HeaderKeys.Algorithm, alg); } IDigest digest; IDigest digest2; if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "PS384": digest = new Sha384Digest(); digest2 = new Sha384Digest(); break; default: throw new Exception("Unknown signature algorithm"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.ECDSA_256: case AlgorithmValuesInt.RSA_PSS_256: digest = new Sha256Digest(); digest2 = new Sha256Digest(); break; case AlgorithmValuesInt.ECDSA_384: case AlgorithmValuesInt.RSA_PSS_384: digest = new Sha384Digest(); digest2 = new Sha384Digest(); break; case AlgorithmValuesInt.ECDSA_512: case AlgorithmValuesInt.RSA_PSS_512: digest = new Sha512Digest(); digest2 = new Sha512Digest(); break; default: throw new CoseException("Unknown signature algorith"); } } else { throw new CoseException("Algorthm incorrectly encoded"); } if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "PS384": { PssSigner signer = new PssSigner(new RsaEngine(), digest, digest2, digest.GetByteLength()); RsaKeyParameters prv = new RsaPrivateCrtKeyParameters(keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_n), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_e), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_d), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_p), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_q), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_dP), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_dQ), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_qInv)); ParametersWithRandom param = new ParametersWithRandom(prv, Message.GetPRNG()); signer.Init(true, param); signer.BlockUpdate(bytesToBeSigned, 0, bytesToBeSigned.Length); return(signer.GenerateSignature()); } default: throw new CoseException("Unknown Algorithm"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.RSA_PSS_256: case AlgorithmValuesInt.RSA_PSS_512: { PssSigner signer = new PssSigner(new RsaEngine(), digest, digest2, digest.GetByteLength()); RsaKeyParameters prv = new RsaPrivateCrtKeyParameters(keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_n), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_e), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_d), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_p), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_q), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_dP), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_dQ), keyToSign.AsBigInteger(CoseKeyParameterKeys.RSA_qInv)); ParametersWithRandom param = new ParametersWithRandom(prv, Message.GetPRNG()); signer.Init(true, param); signer.BlockUpdate(bytesToBeSigned, 0, bytesToBeSigned.Length); return(signer.GenerateSignature()); } case AlgorithmValuesInt.ECDSA_256: case AlgorithmValuesInt.ECDSA_384: case AlgorithmValuesInt.ECDSA_512: { SecureRandom random = Message.GetPRNG(); digest.BlockUpdate(bytesToBeSigned, 0, bytesToBeSigned.Length); byte[] digestedMessage = new byte[digest.GetDigestSize()]; digest.DoFinal(digestedMessage, 0); X9ECParameters p = keyToSign.GetCurve(); ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); ECPrivateKeyParameters privKey = new ECPrivateKeyParameters("ECDSA", ConvertBigNum(keyToSign[CoseKeyParameterKeys.EC_D]), parameters); ParametersWithRandom param = new ParametersWithRandom(privKey, random); ECDsaSigner ecdsa = new ECDsaSigner(new HMacDsaKCalculator(new Sha256Digest())); ecdsa.Init(true, param); BigInteger[] sig = ecdsa.GenerateSignature(digestedMessage); byte[] r = sig[0].ToByteArrayUnsigned(); byte[] s = sig[1].ToByteArrayUnsigned(); int cbR = (p.Curve.FieldSize + 7) / 8; byte[] sigs = new byte[cbR * 2]; Array.Copy(r, 0, sigs, cbR - r.Length, r.Length); Array.Copy(s, 0, sigs, cbR + cbR - s.Length, s.Length); return(sigs); } default: throw new CoseException("Unknown Algorithm"); } } else { throw new CoseException("Algorithm incorrectly encoded"); } }
public static void Write(CBORObject obj, Stream stream) { if (obj.Type == CBORType.Number) { stream.WriteByte(unchecked ((byte)((byte)'i'))); writeUtf8(obj.AsEInteger().ToString(), stream); stream.WriteByte(unchecked ((byte)((byte)'e'))); } else if (obj.Type == CBORType.TextString) { string s = obj.AsString(); long length = DataUtilities.GetUtf8Length(s, false); if (length < 0) { throw new CBORException("invalid string"); } writeUtf8(LongToString(length), stream); stream.WriteByte(unchecked ((byte)((byte)':'))); writeUtf8(s, stream); } else if (obj.Type == CBORType.Map) { var hasNonStringKeys = false; foreach (CBORObject key in obj.Keys) { if (key.Type != CBORType.TextString) { hasNonStringKeys = true; break; } } if (hasNonStringKeys) { var valueSMap = new Dictionary <String, CBORObject>(); // Copy to a map with String keys, since // some keys could be duplicates // when serialized to strings foreach (CBORObject key in obj.Keys) { CBORObject value = obj[key]; string str = (key.Type == CBORType.TextString) ? key.AsString() : key.ToJSONString(); valueSMap[str] = value; } stream.WriteByte(unchecked ((byte)((byte)'d'))); foreach (KeyValuePair <string, CBORObject> entry in valueSMap) { string key = entry.Key; CBORObject value = entry.Value; long length = DataUtilities.GetUtf8Length(key, false); if (length < 0) { throw new CBORException("invalid string"); } writeUtf8( LongToString(length), stream); stream.WriteByte(unchecked ((byte)((byte)':'))); writeUtf8(key, stream); Write(value, stream); } stream.WriteByte(unchecked ((byte)((byte)'e'))); } else { stream.WriteByte(unchecked ((byte)((byte)'d'))); foreach (CBORObject key in obj.Keys) { string str = key.AsString(); long length = DataUtilities.GetUtf8Length(str, false); if (length < 0) { throw new CBORException("invalid string"); } writeUtf8(LongToString(length), stream); stream.WriteByte(unchecked ((byte)((byte)':'))); writeUtf8(str, stream); Write(obj[key], stream); } stream.WriteByte(unchecked ((byte)((byte)'e'))); } } else if (obj.Type == CBORType.Array) { stream.WriteByte(unchecked ((byte)((byte)'l'))); for (var i = 0; i < obj.Count; ++i) { Write(obj[i], stream); } stream.WriteByte(unchecked ((byte)((byte)'e'))); } else { string str = obj.ToJSONString(); long length = DataUtilities.GetUtf8Length(str, false); if (length < 0) { throw new CBORException("invalid string"); } writeUtf8(LongToString(length), stream); stream.WriteByte(unchecked ((byte)((byte)':'))); writeUtf8(str, stream); } }
private byte[] Kdf(byte[] secret, EncryptMessage msg, int cbitKey, string algorithmId) { // Build a long byte array // four byte counter // secret // AlgorithmID - [32-bit size || algorithm identifier ] // PartyUInfo - [32-bit size || PartyUInfo ] ---- "apu" // PartyVInfo - [32-bit size || PartyVInfo ] ---- "apv" // SuppPubInfo - 32-bit - key data len // SuppPrivInfo - nothing byte[] rgbPartyU = new byte[0]; byte[] rgbPartyV = new byte[0]; byte[] algId = Encoding.UTF8.GetBytes(algorithmId); CBORObject j = FindAttr("apu", msg); if (j != null) { rgbPartyU = Message.base64urldecode(j.AsString()); } j = FindAttr("apv", msg); if (j != null) { rgbPartyV = Message.base64urldecode(j.AsString()); } int c = 4 + secret.Length + 4 + algId.Length + 4 + rgbPartyU.Length + 4 + rgbPartyV.Length + 4; byte[] rgb = new byte[c]; // Counter starts at 0 Array.Copy(secret, 0, rgb, 4, secret.Length); c = 4 + secret.Length; if (algorithmId.Length > 255) { throw new JoseException("Internal error"); } rgb[c + 3] = (byte)algId.Length; Array.Copy(algId, 0, rgb, c + 4, algId.Length); c += 4 + algorithmId.Length; if (rgbPartyU.Length > 255) { throw new JoseException("Internal error"); } rgb[c + 3] = (byte)rgbPartyU.Length; Array.Copy(rgbPartyU, 0, rgb, c + 4, rgbPartyU.Length); c += 4 + rgbPartyU.Length; if (rgbPartyV.Length > 255) { throw new JoseException("internal error"); } rgb[c + 3] = (byte)rgbPartyV.Length; Array.Copy(rgbPartyV, 0, rgb, c + 4, rgbPartyV.Length); c += 4 + rgbPartyV.Length; if (cbitKey / (256 * 256) != 0) { throw new JoseException("internal error"); } rgb[c + 3] = (byte)(cbitKey % 256); rgb[c + 2] = (byte)(cbitKey / 256); // Now do iterative hashing IDigest digest = new Sha256Digest(); int cIters = (cbitKey + 255) / 256; byte[] rgbDigest = new byte[256 / 8 * cIters]; for (int i = 0; i < cIters; i++) { rgb[3] = (byte)(i + 1); digest.Reset(); digest.BlockUpdate(rgb, 0, rgb.Length); digest.DoFinal(rgbDigest, (256 / 8) * i); } byte[] rgbOut = new byte[cbitKey / 8]; Array.Copy(rgbDigest, rgbOut, rgbOut.Length); return(rgbOut); }
public static void Write(CBORObject obj, Stream stream) { if (obj.Type == CBORType.Number) { stream.WriteByte(unchecked((byte)((byte)'i'))); writeUtf8(obj.AsEInteger().ToString(), stream); stream.WriteByte(unchecked((byte)((byte)'e'))); } else if (obj.Type == CBORType.TextString) { string s = obj.AsString(); long length = DataUtilities.GetUtf8Length(s, false); if (length < 0) { throw new CBORException("invalid string"); } writeUtf8(LongToString(length), stream); stream.WriteByte(unchecked((byte)((byte)':'))); writeUtf8(s, stream); } else if (obj.Type == CBORType.Map) { var hasNonStringKeys = false; foreach (CBORObject key in obj.Keys) { if (key.Type != CBORType.TextString) { hasNonStringKeys = true; break; } } if (hasNonStringKeys) { var valueSMap = new Dictionary<String, CBORObject>(); // Copy to a map with String keys, since // some keys could be duplicates // when serialized to strings foreach (CBORObject key in obj.Keys) { CBORObject value = obj[key]; string str = (key.Type == CBORType.TextString) ? key.AsString() : key.ToJSONString(); valueSMap[str] = value; } stream.WriteByte(unchecked((byte)((byte)'d'))); foreach (KeyValuePair<string, CBORObject> entry in valueSMap) { string key = entry.Key; CBORObject value = entry.Value; long length = DataUtilities.GetUtf8Length(key, false); if (length < 0) { throw new CBORException("invalid string"); } writeUtf8( LongToString(length), stream); stream.WriteByte(unchecked((byte)((byte)':'))); writeUtf8(key, stream); Write(value, stream); } stream.WriteByte(unchecked((byte)((byte)'e'))); } else { stream.WriteByte(unchecked((byte)((byte)'d'))); foreach (CBORObject key in obj.Keys) { string str = key.AsString(); long length = DataUtilities.GetUtf8Length(str, false); if (length < 0) { throw new CBORException("invalid string"); } writeUtf8(LongToString(length), stream); stream.WriteByte(unchecked((byte)((byte)':'))); writeUtf8(str, stream); Write(obj[key], stream); } stream.WriteByte(unchecked((byte)((byte)'e'))); } } else if (obj.Type == CBORType.Array) { stream.WriteByte(unchecked((byte)((byte)'l'))); for (var i = 0; i < obj.Count; ++i) { Write(obj[i], stream); } stream.WriteByte(unchecked((byte)((byte)'e'))); } else { string str = obj.ToJSONString(); long length = DataUtilities.GetUtf8Length(str, false); if (length < 0) { throw new CBORException("invalid string"); } writeUtf8(LongToString(length), stream); stream.WriteByte(unchecked((byte)((byte)':'))); writeUtf8(str, stream); } }
public bool Validate(Recipient recipientReceiver) { byte[] rgbKey = null; int cbitKey; CBORObject alg = FindAttribute(COSE.HeaderKeys.Algorithm); if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "AES-CMAC-128/64": cbitKey = 128; break; case "AES-CMAC-256/64": cbitKey = 256; break; default: throw new Exception("MAC algorithm is not recognized"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.HMAC_SHA_256_64: case AlgorithmValuesInt.HMAC_SHA_256: cbitKey = 256; break; case AlgorithmValuesInt.HMAC_SHA_384: cbitKey = 384; break; case AlgorithmValuesInt.HMAC_SHA_512: cbitKey = 512; break; case AlgorithmValuesInt.AES_CBC_MAC_128_64: case AlgorithmValuesInt.AES_CBC_MAC_128_128: cbitKey = 128; break; case AlgorithmValuesInt.AES_CBC_MAC_256_64: case AlgorithmValuesInt.AES_CBC_MAC_256_128: cbitKey = 256; break; default: throw new Exception("MAC algorithm not recognized" + alg.AsInt32()); } } else { throw new CoseException("Algorithm incorrectly encoded"); } foreach (Recipient msgRecpient in recipientList) { if (recipientReceiver == msgRecpient) { try { rgbKey = msgRecpient.Decrypt(cbitKey, alg); } catch (CoseException) { } } else if (recipientReceiver == null) { ; } if (rgbKey != null) { break; } } if (rgbKey == null) { throw new CoseException("Recipient not found"); } byte[] rgbCheck; if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "AES-CMAC-128/64": case "AES-CMAC-256/64": rgbCheck = AES_CMAC(alg, rgbKey); break; default: throw new Exception("MAC algorithm is not recognized"); } } else if (alg.Type == CBORType.Number) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.HMAC_SHA_256: case AlgorithmValuesInt.HMAC_SHA_384: case AlgorithmValuesInt.HMAC_SHA_512: case AlgorithmValuesInt.HMAC_SHA_256_64: rgbCheck = HMAC(alg, rgbKey); break; case AlgorithmValuesInt.AES_CBC_MAC_128_64: case AlgorithmValuesInt.AES_CBC_MAC_128_128: case AlgorithmValuesInt.AES_CBC_MAC_256_64: case AlgorithmValuesInt.AES_CBC_MAC_256_128: rgbCheck = AES_CBC_MAC(alg, rgbKey); break; default: throw new Exception("MAC algorithm not recognized" + alg.AsInt32()); } } else { throw new CoseException("Algorithm incorrectly encoded"); } bool fReturn = true; for (int i = 0; i < rgbCheck.Length; i++) { fReturn &= (rgbTag[i] == rgbCheck[i]); } return(fReturn); }
public bool Validate(byte[] rgbKey) { int cbitKey; CBORObject alg = FindAttribute(HeaderKeys.Algorithm); if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "AES-CMAC-128/64": cbitKey = 128; break; case "AES-CMAC-256/64": cbitKey = 256; break; default: throw new CoseException("Unknown Algorithm Specified"); } } else if (alg.Type == CBORType.Integer) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.HMAC_SHA_256_64: case AlgorithmValuesInt.HMAC_SHA_256: cbitKey = 256; break; case AlgorithmValuesInt.HMAC_SHA_384: cbitKey = 384; break; case AlgorithmValuesInt.HMAC_SHA_512: cbitKey = 512; break; case AlgorithmValuesInt.AES_CBC_MAC_128_64: case AlgorithmValuesInt.AES_CBC_MAC_128_128: cbitKey = 128; break; case AlgorithmValuesInt.AES_CBC_MAC_256_64: case AlgorithmValuesInt.AES_CBC_MAC_256_128: cbitKey = 256; break; default: throw new CoseException("MAC algorithm not recognized " + alg.AsInt32()); } } else { throw new CoseException("Algorithm incorrectly encoded"); } if (rgbKey == null) { throw new CoseException("No Key Provided"); } if (cbitKey / 8 != rgbKey.Length) { throw new CoseException("Incorrect key length for operation"); } byte[] rgbCheck; if (alg.Type == CBORType.TextString) { switch (alg.AsString()) { case "AES-CMAC-128/64": case "AES-CMAC-256/64": rgbCheck = AES_CMAC(alg, rgbKey); break; default: throw new CoseException("Unknown Algorithm Specified"); } } else if (alg.Type == CBORType.Integer) { switch ((AlgorithmValuesInt)alg.AsInt32()) { case AlgorithmValuesInt.HMAC_SHA_256: case AlgorithmValuesInt.HMAC_SHA_384: case AlgorithmValuesInt.HMAC_SHA_512: case AlgorithmValuesInt.HMAC_SHA_256_64: rgbCheck = HMAC(alg, rgbKey); break; case AlgorithmValuesInt.AES_CBC_MAC_128_64: case AlgorithmValuesInt.AES_CBC_MAC_128_128: case AlgorithmValuesInt.AES_CBC_MAC_256_64: case AlgorithmValuesInt.AES_CBC_MAC_256_128: rgbCheck = AES_CBC_MAC(alg, rgbKey); break; default: throw new CoseException("MAC algorithm not recognized " + alg.AsInt32()); } } else { throw new CoseException("Algorithm incorrectly encoded"); } bool fReturn = true; for (int i = 0; i < rgbCheck.Length; i++) { fReturn &= (RgbTag[i] == rgbCheck[i]); } return(fReturn); }
internal static void WritePlistToInternalCore( CBORObject obj, StringOutput writer, JSONOptions options, IList <CBORObject> stack) { if (obj.IsNumber) { if (obj.AsNumber().IsInteger()) { writer.WriteString("<integer>"); writer.WriteString(obj.ToJSONString()); writer.WriteString("</integer>"); } else { writer.WriteString("<real>"); writer.WriteString(obj.ToJSONString()); writer.WriteString("</real>"); } return; } if (obj.HasMostOuterTag(0) || obj.HasMostOuterTag(1)) { CBORDateConverter conv = CBORDateConverter.TaggedString; var year = new EInteger[1]; var lesserFields = new int[7]; if (!conv.TryGetDateTimeFields(obj, year, lesserFields)) { throw new InvalidOperationException("Unsupported date/time"); } // Set fractional seconds and offset to 0, since // they're not needed lesserFields[5] = 0; lesserFields[6] = 0; CBORObject newobj = conv.DateTimeFieldsToCBORObject(year[0], lesserFields); writer.WriteString("<date>"); writer.WriteString(newobj.AsString()); writer.WriteString("</date>"); return; } switch (obj.Type) { case CBORType.Integer: { CBORObject untaggedObj = obj.Untag(); writer.WriteString("<integer>"); writer.WriteString(untaggedObj.ToJSONString()); writer.WriteString("</integer>"); break; } case CBORType.FloatingPoint: { CBORObject untaggedObj = obj.Untag(); writer.WriteString("<real>"); writer.WriteString(untaggedObj.ToJSONString()); writer.WriteString("</real>"); break; } case CBORType.Boolean: { if (obj.IsTrue) { writer.WriteString("<true/>"); return; } if (obj.IsFalse) { writer.WriteString("<false/>"); return; } return; } case CBORType.SimpleValue: { // Write all CBOR simple values (other than true and false) as the text string // "null". writer.WriteString("<str"); writer.WriteString("ing>"); writer.WriteString("null"); writer.WriteString("</str"); writer.WriteString("ing>"); return; } case CBORType.ByteString: { byte[] byteArray = obj.GetByteString(); if (byteArray.Length == 0) { writer.WriteString("<data></data>"); return; } if (obj.HasTag(22)) { writer.WriteString("<data>"); // Base64 with padding Base64.WriteBase64( writer, byteArray, 0, byteArray.Length, true); writer.WriteString("</data>"); } else if (obj.HasTag(23)) { writer.WriteString("<str"); writer.WriteString("ing>"); // Write as base16 for (int i = 0; i < byteArray.Length; ++i) { writer.WriteCodePoint((int)Hex16[(byteArray[i] >> 4) & 15]); writer.WriteCodePoint((int)Hex16[byteArray[i] & 15]); } writer.WriteString("</str"); writer.WriteString("ing>"); } else { writer.WriteString("<data>"); // Base64 with padding Base64.WriteBase64( writer, byteArray, 0, byteArray.Length, true); writer.WriteString("</data>"); } break; } case CBORType.TextString: { string thisString = obj.AsString(); if (thisString.Length == 0) { writer.WriteString("<str"); writer.WriteString("ing>"); writer.WriteString("</str"); writer.WriteString("ing>"); return; } writer.WriteString("<str"); writer.WriteString("ing>"); WritePlistStringUnquoted(thisString, writer, options); writer.WriteString("</str"); writer.WriteString("ing>"); break; } case CBORType.Array: { writer.WriteString("<array>"); for (var i = 0; i < obj.Count; ++i) { bool pop = CheckCircularRef(stack, obj, obj[i]); WritePlistToInternalCore(obj[i], writer, options, stack); PopRefIfNeeded(stack, pop); } writer.WriteString("</array>"); break; } case CBORType.Map: { var hasNonStringKeys = false; ICollection <KeyValuePair <CBORObject, CBORObject> > entries = obj.Entries; foreach (KeyValuePair <CBORObject, CBORObject> entry in entries) { CBORObject key = entry.Key; if (key.Type != CBORType.TextString || key.IsTagged) { // treat a non-text-string item or a tagged item // as having non-string keys hasNonStringKeys = true; break; } } if (!hasNonStringKeys) { writer.WriteString("<dict>"); foreach (KeyValuePair <CBORObject, CBORObject> entry in entries) { CBORObject key = entry.Key; CBORObject value = entry.Value; writer.WriteString("<key>"); WritePlistStringUnquoted(key.AsString(), writer, options); writer.WriteString("</key>"); bool pop = CheckCircularRef(stack, obj, value); WritePlistToInternalCore(value, writer, options, stack); PopRefIfNeeded(stack, pop); } writer.WriteString("</dict>"); } else { // This map has non-string keys IDictionary <string, CBORObject> stringMap = new Dictionary <string, CBORObject>(); // Copy to a map with String keys, since // some keys could be duplicates // when serialized to strings foreach (KeyValuePair <CBORObject, CBORObject> entry in entries) { CBORObject key = entry.Key; CBORObject value = entry.Value; string str = null; switch (key.Type) { case CBORType.TextString: str = key.AsString(); break; case CBORType.Array: case CBORType.Map: { var sb = new StringBuilder(); var sw = new StringOutput(sb); bool pop = CheckCircularRef(stack, obj, key); WritePlistToInternalCore(key, sw, options, stack); PopRefIfNeeded(stack, pop); str = sb.ToString(); break; } default: str = key.ToJSONString(options); break; } if (stringMap.ContainsKey(str)) { throw new CBORException( "Duplicate Plist string equivalents of map" + "\u0020keys"); } stringMap[str] = value; } writer.WriteString("<dict>"); foreach (KeyValuePair <string, CBORObject> entry in stringMap) { string key = entry.Key; CBORObject value = entry.Value; writer.WriteString("<key>"); WritePlistStringUnquoted((string)key, writer, options); writer.WriteString("</key>"); bool pop = CheckCircularRef(stack, obj, value); WritePlistToInternalCore(value, writer, options, stack); PopRefIfNeeded(stack, pop); } writer.WriteString("</dict>"); } break; } default: throw new InvalidOperationException("Unexpected item" + "\u0020type"); } }
public void ReverseKey() { CBORObject result = (CBORObject)_dictionary.Reverse(CBORObject.FromObject(1), false); Assert.AreEqual("http://www.iana.org/assignments/relation/item>", result.AsString()); }