Test.ps1
function Encrypt-ColumnEncryptionKey{ Param( [X509Certificate] $Certificate, [string] $MasterKeyPath, #[string] $EncryptionAlgorithm, [byte[]] $ColumnEncryptionKey ) # Construct the encryptedColumnEncryptionKey # Format is # version + keyPathLength + ciphertextLength + ciphertext + keyPath + signature # We currently only support one version $version = [byte[]] @( 0x01 ) # Get the Unicode encoded bytes of cultureinvariant lower case masterKeyPath $masterKeyPathBytes = [System.Text.UnicodeEncoding]::Unicode.GetBytes($masterKeyPath.ToLowerInvariant()) $keyPathLength = [System.BitConverter]::GetBytes([Int16]$masterKeyPathBytes.Length) # Encrypt the plain text $rsa = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPublicKey($Certificate) $cipherText = $rsa.Encrypt($columnEncryptionKey, [System.Security.Cryptography.RSAEncryptionPadding]::OaepSHA1) $cipherTextLength = [System.BitConverter]::GetBytes([Int16]$cipherText.Length) # Compute hash # SHA-2-256(version + keyPathLength + ciphertextLength + keyPath + ciphertext) $sha256 = [System.Security.Cryptography.SHA256CryptoServiceProvider]::new() try { $sha256.TransformBlock($version, 0, $version.Length, $version, 0) > $null $sha256.TransformBlock($keyPathLength, 0, $keyPathLength.Length, $keyPathLength, 0) > $null $sha256.TransformBlock($cipherTextLength, 0, $cipherTextLength.Length, $cipherTextLength, 0) > $null $sha256.TransformBlock($masterKeyPathBytes, 0, $masterKeyPathBytes.Length, $masterKeyPathBytes, 0) > $null $sha256.TransformFinalBlock($cipherText, 0, $cipherText.Length) > $null $hash = $sha256.Hash } finally{ $sha256.Dispose() } # Sign the hash $rsaPrivate = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate) $rsaFormatter = [System.Security.Cryptography.RSAPKCS1SignatureFormatter]::new($rsaPrivate) $rsaFormatter.SetHashAlgorithm("SHA256") $signedHash = $rsaFormatter.CreateSignature($hash) # Construct the encrypted column encryption key # EncryptedColumnEncryptionKey = version + keyPathLength + ciphertextLength + keyPath + ciphertext + signature $encryptedColumnEncryptionKeyLength = $version.Length + $cipherTextLength.Length + $keyPathLength.Length + $cipherText.Length + $masterKeyPathBytes.Length + $signedHash.Length $encryptedColumnEncryptionKey = [byte[]]::new($encryptedColumnEncryptionKeyLength) # Copy version byte $currentIndex = 0; [System.Buffer]::BlockCopy($version, 0, $encryptedColumnEncryptionKey, $currentIndex, $version.Length) $currentIndex += $version.Length # Copy key path length [System.Buffer]::BlockCopy($keyPathLength, 0, $encryptedColumnEncryptionKey, $currentIndex, $keyPathLength.Length) > $null $currentIndex += $keyPathLength.Length # Copy ciphertext length [System.Buffer]::BlockCopy($cipherTextLength, 0, $encryptedColumnEncryptionKey, $currentIndex, $cipherTextLength.Length) > $null $currentIndex += $cipherTextLength.Length # Copy key path [System.Buffer]::BlockCopy($masterKeyPathBytes, 0, $encryptedColumnEncryptionKey, $currentIndex, $masterKeyPathBytes.Length) > $null $currentIndex += $masterKeyPathBytes.Length # Copy ciphertext [System.Buffer]::BlockCopy($cipherText, 0, $encryptedColumnEncryptionKey, $currentIndex, $cipherText.Length) > $null $currentIndex += $cipherText.Length # copy the signature [System.Buffer]::BlockCopy($signedHash, 0, $encryptedColumnEncryptionKey, $currentIndex, $signedHash.Length) > $null return $encryptedColumnEncryptionKey } # $masterKeyName = "TESTMK4" $masterKeyCertificatePath = "CurrentUser/My/797151D4A7F9F4C69912CBB871E12CBEAC315F39" $masterKeyCertificate = [X509Certificate] (Get-Item -Path "Cert://$masterKeyCertificatePath") # $newMasterKeyScript = "CREATE COLUMN MASTER KEY $masterKeyName WITH ( # KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE', # KEY_PATH = '$masterKeyCertificatePath' # ); # " $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() try{ $encryptionKey = [byte[]]::new(32) $rng.GetBytes($encryptionKey) } finally{ $rng.Dispose() } # $encryptionKeyName = "CEK3" $encryptedKey = Encrypt-ColumnEncryptionKey -Certificate $masterKeyCertificate -MasterKeyPath $masterKeyCertificatePath -ColumnEncryptionKey $encryptionKey $encryptedKeySerialized = "0x" + [BitConverter]::ToString($encryptedKey).Replace("-", "") $encryptedKeySerialized # $newEncryptionKeyScript = "CREATE COLUMN ENCRYPTION KEY $encryptionKeyName WITH VALUES ( # COLUMN_MASTER_KEY = $masterKeyName, # ALGORITHM = 'RSA_OAEP', # ENCRYPTED_VALUE = $encryptedKeySerialized # ); # " # $script = " # BEGIN TRANSACTION # $newMasterKeyScript # GO # $newEncryptionKeyScript # GO # COMMIT TRANSACTION # " # Invoke-SqlCmd -ServerInstance "(local)" -Database "STTI_INT" -Query $script -ErrorAction Stop |