示例#1
0
        /// <summary>
        /// Get the key identifier for the signature
        /// </summary>
        private String GetAppKeyId()
        {
            // Is there a key called jwsdefault? If so, use it as the default signature key
            if (m_signingService.GetKeys().Contains("jwsdefault"))
            {
                return("jwsdefault");
            }

            // Otherwise use the configured secure application HMAC key as the default
            if (AuthenticationContext.Current.Principal is IClaimsPrincipal claimsPrincipal)
            {
                // Is there a tag for their application
                var appId = claimsPrincipal.FindFirst(SanteDBClaimTypes.SanteDBApplicationIdentifierClaim)?.Value;
                if (String.IsNullOrEmpty(appId))
                {
                    throw new InvalidOperationException("Can only generate signed pointers when authenticated");
                }
                var keyId = $"SA.{appId}";

                // Does the key provider have the key for this app?
                if (m_signingService.GetKeys().Any(k => k == keyId))
                {
                    return(keyId);
                }
                else
                {
                    // Application identity
                    var appIdentity = claimsPrincipal.Identities.OfType <IApplicationIdentity>().FirstOrDefault();
                    if (appIdentity == null)
                    {
                        this.m_tracer.TraceWarning("No application identity could be found in principal (available identities: {0})", String.Join(",", claimsPrincipal.Identities.Select(o => o.GetType())));
                        throw new InvalidOperationException("No application identity found in principal");
                    }
                    var key = this.m_applicationIdService.GetSecureKey(appIdentity.Name);

                    // Get the key
                    this.m_signingService.AddSigningKey(keyId, key, "HS256");

                    return(keyId);
                }
            }
            else
            {
                throw new InvalidOperationException("Cannot generate a personal key without knowing application id");
            }
        }
示例#2
0
        /// <summary>
        /// Read from the stream
        /// </summary>
        public static PeerTransferPayload Read(Stream s, IDataSigningService signingProvider, bool validateSignature)
        {
            byte[] hdr = new byte[7];
            s.Read(hdr, 0, 7);
            if (!hdr.Take(5).SequenceEqual(MAGIC_HEADER))
            {
                throw new FormatException("Invalid payload");
            }
            else if (hdr[5] >= VERSION_ID)
            {
                throw new InvalidOperationException($"Payload version {hdr[5]} is greater than supported version of {VERSION_ID}");
            }

            var retVal = new PeerTransferPayload();

            retVal.Encoding = (PeerTransferEncodingFlags)hdr[6];

            // Read the rest of the stream
            if (retVal.Encoding.HasFlag(PeerTransferEncodingFlags.Compressed))
            {
                s = new GZipStream(s, SharpCompress.Compressors.CompressionMode.Decompress);
            }

            using (var sr = new StreamReader(s))
            {
                var data = sr.ReadToEnd();
                // Read the JWS header
                var match = s_jwsFormat.Match(data);
                if (!match.Success)
                {
                    throw new FormatException("Payload must be in JWS format");
                }

                // Get the parts of the header
                byte[] headerBytes = match.Groups[1].Value.ParseBase64UrlEncode(),
                bodyBytes      = match.Groups[2].Value.ParseBase64UrlEncode(),
                signatureBytes = match.Groups[3].Value.ParseBase64UrlEncode();

                // Now lets parse the JSON objects
                dynamic header = JsonConvert.DeserializeObject(System.Text.Encoding.UTF8.GetString(headerBytes));
                dynamic body   = JsonConvert.DeserializeObject(System.Text.Encoding.UTF8.GetString(bodyBytes));

                // Now validate the payload
                if (!header.typ.ToString().StartsWith("x-santedb+"))
                {
                    throw new InvalidOperationException("Cannot determine type of data");
                }

                var    type      = new ModelSerializationBinder().BindToType(null, header.typ.ToString().Substring(10));
                var    algorithm = header.alg.ToString();
                String keyId     = header.key.ToString();

                // Validate the signature if we have the key
                if (validateSignature)
                {
                    // We have the key?
                    if (!signingProvider.GetKeys().Any(k => k == keyId))
                    {
                        throw new InvalidOperationException("Cannot find appropriate validation key");
                    }

                    if (signingProvider.GetSignatureAlgorithm(keyId) != algorithm)
                    {
                        throw new InvalidOperationException("Invalid signature algorithm");
                    }

                    var payload = System.Text.Encoding.UTF8.GetBytes($"{match.Groups[1].Value}.{match.Groups[2].Value}");

                    if (!signingProvider.Verify(payload, signatureBytes, keyId))
                    {
                        throw new SecurityException("Cannot verify authenticity of the specified data payload");
                    }
                }

                retVal.Payload = JsonConvert.DeserializeObject(System.Text.Encoding.UTF8.GetString(bodyBytes), type);
                // Return the result
                return(retVal);
            }
        }