internal BlobStream(ConnectPackageCreationParameters connectPackageParameters, Blob blob) { _connectPackageParameters = connectPackageParameters; _blob = blob; _length = blob.ContentLength; _canWrite = true; }
private static string WriteConnectPackageParametersXml( ConnectPackageCreationParameters creationParameters, PasswordProtectedPackage package) { StringBuilder request = new StringBuilder(512); XmlWriterSettings settings = new XmlWriterSettings(); settings.ConformanceLevel = ConformanceLevel.Fragment; using (XmlWriter writer = XmlWriter.Create(request, settings)) { if (creationParameters.IdentityCode != null) { writer.WriteElementString("identity-code", creationParameters.IdentityCode); } writer.WriteElementString("friendly-name", creationParameters.FriendlyName); writer.WriteElementString("question", creationParameters.SecurityQuestion); writer.WriteElementString("external-id", creationParameters.ApplicationPatientId); writer.WriteRaw(package.GetItemXml("package")); WritePackageBlobRefUrls(creationParameters.PackageBlobReferenceUrls, writer); } return request.ToString(); }
/// <summary> /// Asks HealthVault to create a pending package for the application specified /// by the connection with the specified user specific parameters and the pre-allocated /// identity code. /// </summary> /// /// <remarks> /// The password protected package supports 2 encryption algorithms, AES256 (recommended) /// and TripleDES. /// <br/><br/> /// For AES256, the supported key size is 256 bits, the blocksize is 256 bits, the IV /// length is 32 bytes. /// <br/><br/> /// For TripleDES, the supported key size is 192 bits, the blocksize is 64 bits, the IV /// length is 8 bytes. /// <br/><br/> /// The encryption key should be derived using the answer, the salt, and the number of hash /// iterations. The decryption will generate this key via the /// <see cref="Rfc2898DeriveBytes"/> class, hence, encryption should use a similar or /// identical process. To ensure case-insensitivity, the answer should be converted to its /// lower cased form using <see cref="String.ToLowerInvariant()"/> (culturally-agnostic) /// prior to generating the derived key. /// <br/><br/> /// The algorithm used has the following parameters: /// <ul> /// <li>Mode = CipherMode.CBC</li> /// <li>Padding = PaddingMode.ISO10126</li> /// </ul> /// <br/><br/> /// The salt supplied is used as the salt to the derived key as well as the key to the /// supplied HMAC. The salt should be at least 8 bytes long. /// <br/><br/> /// It is recommended that the number of hash iterations be at least 10000. /// </remarks> /// /// <param name="creationParameters"> /// The parameters to use when creating the package. /// </param> /// /// <param name="connectPackage"> /// The pending connect package that the user will add to his/her record. /// This package's /// <see cref="HealthRecordItem"/>'s <see cref="BlobStore"/> must be an encrypted /// blob of xml that represents a list of HealthRecordItems. This xml blob /// must be a sequence of <thing/> elements, each wrapping the XML representation of a /// single HealthRecordItem. Each <thing/> element may be generated by calling /// <see cref="HealthRecordItem.GetItemXml()"/>. /// </param> /// /// <returns> /// A token that the application must give to the patient to use when validating the /// connection request. /// </returns> /// /// <exception cref="HealthServiceException"> /// If an error occurs when contacting HealthVault. /// </exception> /// public virtual string CreateConnectPackage( ConnectPackageCreationParameters creationParameters, PasswordProtectedPackage connectPackage) { Validator.ThrowIfArgumentNull( connectPackage, "connectPackage", "PackageCreatePPPMissingMandatory"); HealthServiceRequest request = new HealthServiceRequest(creationParameters.Connection, "CreateConnectPackage", 2); request.Parameters = WriteConnectPackageParametersXml( creationParameters, connectPackage); request.Execute(); XPathExpression infoPath = SDKHelper.GetInfoXPathExpressionForMethod( request.Response.InfoNavigator, "CreateConnectPackage"); XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(infoPath); return infoNav.SelectSingleNode("identity-code").Value; }
/// <summary> /// Asks HealthVault to create a pending package for the application specified /// by the connection with the specified user specific parameters and the pre-allocated /// identity code. /// </summary> /// /// <remarks> /// The password protected package supports 2 encryption algorithms, AES256 (recommended) /// and TripleDES. /// <br/><br/> /// For AES256, the supported key size is 256 bits, the blocksize is 256 bits, the IV /// length is 32 bytes. /// <br/><br/> /// For TripleDES, the supported key size is 192 bits, the blocksize is 64 bits, the IV /// length is 8 bytes. /// <br/><br/> /// The encryption key should be derived using the answer, the salt, and the number of hash /// iterations. The decryption will generate this key via the /// <see cref="Rfc2898DeriveBytes"/> class, hence, encryption should use a similar or /// identical process. To ensure case-insensitivity, the answer should be converted to its /// lower cased form using <see cref="String.ToLowerInvariant()"/> (culturally-agnostic) /// prior to generating the derived key. /// <br/><br/> /// The algorithm used has the following parameters: /// <ul> /// <li>Mode = CipherMode.CBC</li> /// <li>Padding = PaddingMode.ISO10126</li> /// </ul> /// <br/><br/> /// The salt supplied is used as the salt to the derived key as well as the key to the /// supplied HMAC. The salt should be at least 8 bytes long. /// <br/><br/> /// It is recommended that the number of hash iterations be at least 10000. /// </remarks> /// /// <param name="creationParameters"> /// The parameters to use when creating the package. /// </param> /// /// <param name="connectPackage"> /// The pending connect package that the user will add to his/her record. /// This package's /// <see cref="HealthRecordItem"/>'s <see cref="BlobStore"/> must be an encrypted /// blob of xml that represents a list of HealthRecordItems. This xml blob /// must be a sequence of <thing/> elements, each wrapping the XML representation of a /// single HealthRecordItem. Each <thing/> element may be generated by calling /// <see cref="HealthRecordItem.GetItemXml()"/>. /// </param> /// /// <returns> /// A token that the application must give to the patient to use when validating the /// connection request. /// </returns> /// /// <exception cref="HealthServiceException"> /// If an error occurs when contacting HealthVault. /// </exception> /// public static string CreateConnectPackage( ConnectPackageCreationParameters creationParameters, PasswordProtectedPackage connectPackage) { return HealthVaultPlatformPatientConnect.Current.CreateConnectPackage( creationParameters, connectPackage); }
/// <summary> /// Constructs an instance of the Blob class with the specified values. /// </summary> /// /// <param name="name"> /// The name of the BLOB. It can be <see cref="String.Empty"/> but cannot be <b>null</b>. /// </param> /// /// <param name="contentType"> /// The content type of the BLOB. /// </param> /// /// <param name="currentContentEncoding"> /// The current content encoding of the BLOB or <b>null</b> if the BLOB is not encoded. /// </param> /// /// <param name="legacyContentEncoding"> /// The previous content encoding of the BLOB (if any). /// </param> /// /// <param name="hashInfo"> /// The hash information for the BLOB. /// </param> /// /// <param name="connectPackageParameters"> /// The creation parameters for the <see cref="ConnectPackage"/> that will host the /// <see cref="HealthRecordItem"/> that contains this blob. /// </param> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="name"/> or <paramref name="contentType"/> /// or <paramref name="connectPackageParameters"/> is <b>null</b>. /// </exception> /// internal Blob( string name, string contentType, string currentContentEncoding, string legacyContentEncoding, BlobHashInfo hashInfo, ConnectPackageCreationParameters connectPackageParameters) { Validator.ThrowIfArgumentNull(name, "name", "StringNull"); Validator.ThrowIfArgumentNull(contentType, "contentType", "StringNull"); Validator.ThrowIfArgumentNull(connectPackageParameters, "connectPackageParameters", "ArgumentNull"); _name = name; _contentType = contentType; _contentEncoding = currentContentEncoding; _legacyContentEncoding = legacyContentEncoding; _blobHashInfo = hashInfo; _connectPackageParameters = connectPackageParameters; }
private static string CreatePackageWithContentsAllParameters( ConnectPackageCreationParameters creationParameters, IList<HealthRecordItem> packageContents) { // Obtain the data to encrypt StringBuilder xmlContents = new StringBuilder(); Validator.ThrowArgumentExceptionIf( packageContents == null || packageContents.Count == 0, "packageContents", "PackageCreateHRIMissingMandatory"); for (int i = 0; i < packageContents.Count; ++i) { Validator.ThrowArgumentExceptionIf( packageContents[i] == null, "packageContents", "PackageCreateHRIMissingMandatory"); foreach (Blob blob in packageContents[i].GetBlobStore( default(HealthRecordAccessor)).Values) { if (blob.Url != null) { if (packageContents[i].HealthRecordItemSignatures.Count > 0) { throw Validator.NotSupportedException("PackageCreateSignedWithStreamedBlobsNotSupported"); } creationParameters.PackageBlobReferenceUrls.Add(blob.Url); } } xmlContents.Append(packageContents[i].GetItemXml()); } string dataToEncrypt = xmlContents.ToString(); // Uses AES256 by default PasswordProtectedPackage connectPackage = new PasswordProtectedPackage( creationParameters.PasswordProtectAlgorithm, creationParameters.Salt, creationParameters.ConnectPackageEncryptionAlgorithm.KeySize); byte[] encryptedData = SignAndEncrypt( dataToEncrypt, creationParameters.ConnectPackageHMACAlgorithm, creationParameters.ConnectPackageEncryptionAlgorithm); BlobStore store = connectPackage.GetBlobStore(default(HealthRecordAccessor)); store.WriteInline(String.Empty, "application/octet-stream", encryptedData); return HealthVaultPlatform.CreateConnectPackage( creationParameters, connectPackage); }
/// <summary> /// Asks HealthVault to create a pending package for the application specified /// by the connection with the specified user specific parameters. /// </summary> /// /// <remarks> /// The encryption is delegated to the .NET Crypto classes. The encryption algorithm /// supported by default is AES256. If TripleDES is required, the caller should create /// the custom Password Protected Package and call <see cref="Create(Microsoft.Health.Web.OfflineWebApplicationConnection, string, string, string, Microsoft.Health.ItemTypes.PasswordProtectedPackage)"/>. /// <br/><br/> /// The answer key provided is not the actual key to the decryption. A key is derived using /// the answer, the salt, and the number of hash iterations (via the /// <see cref="Rfc2898DeriveBytes"/> class). To ensure case-insensitivity, the answer /// is lower cased using <see cref="String.ToLowerInvariant()"/> (culturally-agnostic) /// prior to generating the derived key. /// <br/><br/> /// The algorithm used has the following parameters: /// <ul> /// <li>Mode = CipherMode.CBC</li> /// <li>Padding = PaddingMode.ISO10126</li> /// </ul> /// <br/><br/> /// The salt supplied is used as the salt to the derived key as well as the key to the /// supplied HMAC. The data must be appended to the hash, then encrypted and then Base64 /// encoded. /// </remarks> /// /// <param name="connection"> /// The application connection to HealthVault. The application ID in the connection is used /// when making the patient connection. /// </param> /// /// <param name="identityCode"> /// The application unique identifier of the package. /// </param> /// /// <param name="friendlyName"> /// A friendly name for the patient connection which will be shown to the user when they /// go to HealthVault Shell to validate the connection. /// </param> /// /// <param name="securityQuestion"> /// A question (usually provided by the patient) to which the patient must provide the /// <paramref name="securityAnswer"/> when they go to validate the connection in /// the HealthVault Shell. /// </param> /// /// <param name="securityAnswer"> /// The answer to the <paramref name="securityQuestion"/> which the patient must use /// when adding the package to their record via HealthVault Shell. The answer is /// case-insensitive but otherwise must match exactly. Additionally, it must be at least /// 6 characters long. /// </param> /// /// <param name="applicationPatientId"> /// The application specific identifier for the user. This identifier is used to uniquely /// identify the user in the application data storage, whereas the HealthVault person ID is /// used to identify the person in HealthVault. /// </param> /// /// <param name="packageContents"> /// The list of HealthRecordItems that will be encrypted and added to the package that the /// user will claim via HealthVault Shell. /// </param> /// /// <returns> /// A token that the application must give to the patient to use when validating the /// connection request. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="connection"/> is <b>null</b>. /// </exception> /// /// <exception cref="ArgumentException"> /// If <paramref name="identityCode"/>, <paramref name="friendlyName"/>, <paramref name="securityQuestion"/>, /// <paramref name="securityAnswer"/>, <paramref name="applicationPatientId"/> or /// any element in <paramref name="packageContents"/> are /// <b>null</b> or empty. /// </exception> /// /// <exception cref="ArgumentOutOfRangeException"> /// If <paramref name="securityAnswer"/> is less than 6 characters. /// </exception> /// /// <exception cref="NotSupportedException"> /// One of the items in <paramref name="packageContents"/> is signed and contains /// streamed blobs. This is not supported. /// </exception> /// /// <exception cref="HealthServiceException"> /// If an error occurs when contacting HealthVault. /// </exception> /// public static string CreatePackage( OfflineWebApplicationConnection connection, string identityCode, string friendlyName, string securityQuestion, string securityAnswer, string applicationPatientId, IList<HealthRecordItem> packageContents) { ConnectPackageCreationParameters creationParameters = new ConnectPackageCreationParameters( connection, identityCode, friendlyName, securityQuestion, securityAnswer, applicationPatientId); return CreatePackageWithContentsAllParameters( creationParameters, packageContents); }
/// <summary> /// Asks HealthVault to create a pending package for the application specified /// by the connection with the specified user specific parameters and the pre-allocated /// identity code. /// </summary> /// /// <remarks> /// The password protected package supports 2 encryption algorithms, AES256 (recommended) /// and TripleDES. /// <br/><br/> /// For AES256, the supported key size is 256 bits, the blocksize is 256 bits, the IV /// length is 32 bytes. /// <br/><br/> /// For TripleDES, the supported key size is 192 bits, the blocksize is 64 bits, the IV /// length is 8 bytes. /// <br/><br/> /// The encryption key should be derived using the answer, the salt, and the number of hash /// iterations. The decryption will generate this key via the /// <see cref="Rfc2898DeriveBytes"/> class, hence, encryption should use a similar or /// identical process. To ensure case-insensitivity, the answer should be converted to its /// lower cased form using <see cref="String.ToLowerInvariant()"/> (culturally-agnostic) /// prior to generating the derived key. /// <br/><br/> /// The algorithm used has the following parameters: /// <ul> /// <li>Mode = CipherMode.CBC</li> /// <li>Padding = PaddingMode.ISO10126</li> /// </ul> /// <br/><br/> /// The salt supplied is used as the salt to the derived key as well as the key to the /// supplied HMAC. The salt should be at least 8 bytes long. /// <br/><br/> /// It is recommended that the number of hash iterations be at least 10000. /// </remarks> /// /// <param name="connection"> /// The application connection to HealthVault. The application ID in the connection is used /// when making the patient connection. /// </param> /// /// <param name="identityCode"> /// A package identity token previously obtained from <see cref="ConnectPackage.AllocatePackageId"/>. /// </param> /// /// <param name="friendlyName"> /// A friendly name for the patient connection which will be shown to the user when they /// go to HealthVault Shell to validate the connection. /// </param> /// /// <param name="securityQuestion"> /// A question (usually provided by the patient) to which the patient must provide the /// answer when they go to validate the connection in the /// HealthVault Shell. /// </param> /// /// <param name="applicationPatientId"> /// The application specific identifier for the user. This identifier is used to uniquely /// identify the user in the application data storage whereas the HealthVault person ID is /// used to identify the person in HealthVault. /// </param> /// /// <param name="connectPackage"> /// The pending connect package that the user will add to his/her record. /// This package's /// <see cref="HealthRecordItem"/>'s <see cref="BlobStore"/> must be an encrypted /// blob of xml that represents a list of HealthRecordItems. This xml blob /// must be a sequence of <thing/> elements, each wrapping the XML representation of a /// single HealthRecordItem. Each <thing/> element may be generated by calling /// <see cref="HealthRecordItem.GetItemXml()"/>. /// </param> /// /// <returns> /// A token that the application must give to the patient to use when validating the /// connection request. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="connection"/> is <b>null</b>. /// </exception> /// /// <exception cref="ArgumentException"> /// If <paramref name="identityCode"/>, <paramref name="friendlyName"/>, /// <paramref name="securityQuestion"/>, /// <paramref name="applicationPatientId"/>, or <paramref name="connectPackage"/> is /// <b>null</b> or empty. /// </exception> /// /// <exception cref="HealthServiceException"> /// If an error occurs when contacting HealthVault. /// </exception> /// public static string Create( OfflineWebApplicationConnection connection, string identityCode, string friendlyName, string securityQuestion, string applicationPatientId, PasswordProtectedPackage connectPackage) { Validator.ThrowIfStringNullOrEmpty(identityCode, "identityCode"); ConnectPackageCreationParameters creationParameters = new ConnectPackageCreationParameters( connection, identityCode, friendlyName, securityQuestion, null, applicationPatientId, false, true); return HealthVaultPlatform.CreateConnectPackage( creationParameters, connectPackage); }
/// <summary> /// Asks HealthVault to create a pending package for the application specified /// by the connection with the specified user specific parameters. /// </summary> /// /// <remarks> /// The password protected package supports 2 encryption algorithms, AES256 (recommended) /// and TripleDES. /// <br/><br/> /// For AES256, the supported key size is 256 bits, the blocksize is 256 bits, the IV /// length is 32 bytes. /// <br/><br/> /// For TripleDES, the supported key size is 192 bits, the blocksize is 64 bits, the IV /// length is 8 bytes. /// <br/><br/> /// The encryption key should be derived using the answer, the salt, and the number of hash /// iterations. The decryption will generate this key via the /// <see cref="Rfc2898DeriveBytes"/> class, hence, encryption should use a similar or /// identical process. To ensure case-insensitivity, the answer should be converted to its /// lower cased form using <see cref="String.ToLowerInvariant()"/> (culturally-agnostic) /// prior to generating the derived key. /// <br/><br/> /// The algorithm used has the following parameters: /// <ul> /// <li>Mode = CipherMode.CBC</li> /// <li>Padding = PaddingMode.ISO10126</li> /// </ul> /// <br/><br/> /// The salt supplied is used as the salt to the derived key as well as the key to the /// supplied HMAC. The salt should be at least 8 bytes long. /// <br/><br/> /// It is recommended that the number of hash iterations be at least 10000. /// </remarks> /// /// <param name="connection"> /// The application connection to HealthVault. The application ID in the connection is used /// when making the patient connection. /// </param> /// /// <param name="friendlyName"> /// A friendly name for the patient connection which will be shown to the user when they /// go to HealthVault Shell to validate the connection. /// </param> /// /// <param name="securityQuestion"> /// A question (usually provided by the patient) to which the patient must provide the /// answer when they go to validate the connection in the /// HealthVault Shell. /// </param> /// /// <param name="applicationPatientId"> /// The application specific identifier for the user. This identifier is used to uniquely /// identify the user in the application data storage whereas the HealthVault person ID is /// used to identify the person in HealthVault. /// </param> /// /// <param name="connectPackage"> /// The pending connect package that the user will add to his/her record. This package's /// <see cref="Blob"/> must be an encrypted and Base64 /// encoded blob of xml that represents a list of HealthRecordItems. This xml blob /// must be a sequence of <thing/> elements, each wrapping the XML representation of a /// single HealthRecordItem. Each <thing/> element may be generated by calling /// <see cref="HealthRecordItem.GetItemXml()"/>. /// </param> /// /// <returns> /// A token that the application must give to the patient to use when validating the /// connection request. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="connection"/> is <b>null</b>. /// </exception> /// /// <exception cref="ArgumentException"> /// If <paramref name="friendlyName"/>, <paramref name="securityQuestion"/>, /// <paramref name="applicationPatientId"/>, or <paramref name="connectPackage"/> is /// <b>null</b> or empty. /// </exception> /// /// <exception cref="HealthServiceException"> /// If an error occurs when contacting HealthVault. /// </exception> /// public static string Create( OfflineWebApplicationConnection connection, string friendlyName, string securityQuestion, string applicationPatientId, PasswordProtectedPackage connectPackage) { ConnectPackageCreationParameters creationParameters = new ConnectPackageCreationParameters( connection, null, friendlyName, securityQuestion, null, applicationPatientId, false, false); return HealthVaultPlatform.CreateConnectPackage( creationParameters, connectPackage); }
/// <summary> /// Represents a package of user data that is created by HealthVault in order /// to be retrieved by a user using the HealthVault Shell. /// </summary> /// /// <remarks> /// Package encryption is delegated to the .NET Crypto classes. The encryption algorithm /// supported by default is AES256. If TripleDES is required, the caller should create /// the custom Password Protected Package and call <see cref="Create(Microsoft.Health.Web.OfflineWebApplicationConnection, string, string, string, Microsoft.Health.ItemTypes.PasswordProtectedPackage)"/>. /// <br/><br/> /// The answer key provided is not the actual key to the decryption. A key is derived using /// the answer, the salt, and the number of hash iterations (via the /// <see cref="Rfc2898DeriveBytes"/> class). To ensure case-insensitivity, the answer /// is lower cased using <see cref="String.ToLowerInvariant()"/> (culturally-agnostic) /// prior to generating the derived key. /// <br/><br/> /// The algorithm used has the following parameters: /// <ul> /// <li>Mode = CipherMode.CBC</li> /// <li>Padding = PaddingMode.ISO10126</li> /// </ul> /// <br/><br/> /// The salt supplied is used as the salt to the derived key as well as the key to the /// supplied HMAC. The data must be appended to the hash, then encrypted and then Base64 /// encoded. /// </remarks> ///<param name="creationParameters"> /// The <see cref="ConnectPackageCreationParameters"/> to be used while creating the /// connect package. ///</param> /// /// <param name="packageContents"> /// The list of HealthRecordItems that will be encrypted and added to the package that the /// user will claim via HealthVault Shell. /// </param> /// /// <exception cref="NotSupportedException"> /// One of the items in <paramref name="packageContents"/> is signed and contains /// streamed blobs. This is not supported. /// </exception> /// /// <exception cref="HealthServiceException"> /// If an error occurs when contacting HealthVault. /// </exception> /// /// <returns> /// A token that the application must give to the patient to use when validating the /// connection request. /// </returns> /// public static string Create( ConnectPackageCreationParameters creationParameters, IList<HealthRecordItem> packageContents) { return CreatePackageWithContentsAllParameters( creationParameters, packageContents); }