Skip to content

Instantly share code, notes, and snippets.

@realslacker
Last active November 15, 2020 18:59
Show Gist options
  • Save realslacker/b14f686ecd6dbcc229da5cb7a1ca92d9 to your computer and use it in GitHub Desktop.
Save realslacker/b14f686ecd6dbcc229da5cb7a1ca92d9 to your computer and use it in GitHub Desktop.
Work with mRemoteNG passwords... Functionality has been rolled into https://github.com/realslacker/PSmRemoteNG
Add-Type -Path 'C:\Program Files (x86)\mRemoteNG\BouncyCastle.Crypto.dll'
function ConvertFrom-MRNGSecurePassword {
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]
$EncryptedMessage,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[securestring]
$EncryptionKey
)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto( [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $EncryptionKey ) )
$EncryptedMessageBytes = [convert]::FromBase64String( $EncryptedMessage )
$Engine = [Org.BouncyCastle.Crypto.Engines.AesEngine]::new()
$Cipher = [Org.BouncyCastle.Crypto.Modes.GcmBlockCipher]::new($Engine)
$Encoding = [System.Text.Encoding]::UTF8
$SecureRandom = [Org.BouncyCastle.Security.SecureRandom]::new()
$NonceBitSize = 128
$MacBitSize = 128
$KeyBitSize = 256
$SaltBitSize = 128
$KeyDerivationIterations = 1000
$MinPasswordLength = 1
$Salt = New-Object byte[] ( $SaltBitSize/8 )
[array]::Copy( $EncryptedMessageBytes, 0, $Salt, 0, $Salt.Length )
Write-Verbose ( "Salt: {0}" -f ($Salt -join ',') ) -Verbose
$PasswordInBytes = [Org.BouncyCastle.Crypto.PbeParametersGenerator]::Pkcs5PasswordToBytes( $Password.ToCharArray() )
$KeyGenerator = [Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator]::new()
$KeyGenerator.Init( $PasswordInBytes, $Salt, $KeyDerivationIterations )
$KeyParameter = $KeyGenerator.GenerateDerivedMacParameters($KeyBitSize)
$KeyBytes = $KeyParameter.GetKey()
$CipherStream = New-Object System.IO.MemoryStream (, $EncryptedMessageBytes )
$CipherReader = New-Object System.IO.BinaryReader ( $CipherStream )
$Payload = $CipherReader.ReadBytes( $Salt.Length )
$Nonce = $CipherReader.ReadBytes( $NonceBitSize / 8 )
Write-Verbose ( 'Nonce: {0}' -f ( $Nonce -join ',' ) ) -Verbose
$Parameters = [Org.BouncyCastle.Crypto.Parameters.AeadParameters]::new( $KeyParameter, $MacBitSize, $Nonce, $Payload )
$Cipher.Init( $false, $Parameters )
$CipherTextBytes = $CipherReader.ReadBytes( $EncryptedMessageBytes.Length - $Nonce.Length )
$PlainText = New-Object byte[] ( $Cipher.GetOutputSize( $CipherTextBytes.Length ) )
$Len = $Cipher.ProcessBytes( $CipherTextBytes, 0, $CipherTextBytes.Length, $PlainText, 0 )
$Cipher.DoFinal( $PlainText, $Len ) > $null
$Encoding.GetString( $PlainText )
}
function ConvertTo-MRNGSecurePassword {
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]
$Message,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[securestring]
$EncryptionKey
)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto( [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $EncryptionKey ) )
$MessageBytes = $Encoding.GetBytes($Message)
$Engine = [Org.BouncyCastle.Crypto.Engines.AesEngine]::new()
$Cipher = [Org.BouncyCastle.Crypto.Modes.GcmBlockCipher]::new($Engine)
$Encoding = [System.Text.Encoding]::UTF8
$SecureRandom = [Org.BouncyCastle.Security.SecureRandom]::new()
$NonceBitSize = 128
$MacBitSize = 128
$KeyBitSize = 256
$SaltBitSize = 128
$KeyDerivationIterations = 1000
$MinPasswordLength = 1
$Salt = New-Object byte[] ( $SaltBitSize/8 )
$SecureRandom.NextBytes($Salt)
Write-Verbose ( "Salt: {0}" -f ($Salt -join ',') ) -Verbose
$PasswordInBytes = [Org.BouncyCastle.Crypto.PbeParametersGenerator]::Pkcs5PasswordToBytes( $Password.ToCharArray() )
$KeyGenerator = [Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator]::new()
$KeyGenerator.Init( $PasswordInBytes, $Salt, $KeyDerivationIterations )
$KeyParameter = $KeyGenerator.GenerateDerivedMacParameters($KeyBitSize)
$KeyBytes = $KeyParameter.GetKey()
$Payload = New-Object byte[] ( $Salt.Length )
[array]::Copy( $Salt, 0, $Payload, 0, $Salt.Length )
$Nonce = New-Object byte[] ( $NonceBitSize / 8 )
$SecureRandom.NextBytes( $Nonce, 0, $Nonce.Length )
Write-Verbose ( 'Nonce: {0}' -f ( $Nonce -join ',' ) ) -Verbose
$Parameters = [Org.BouncyCastle.Crypto.Parameters.AeadParameters]::new( $KeyParameter, $MacBitSize, $Nonce, $Payload )
$Cipher.Init( $true, $Parameters )
$CipherText = New-Object byte[] ($Cipher.GetOutputSize( $MessageBytes.Length ))
$Len = $Cipher.ProcessBytes( $MessageBytes, 0, $MessageBytes.Length, $CipherText, 0 )
$Cipher.DoFinal( $CipherText, $Len ) > $null
$CombinedStream = New-Object System.IO.MemoryStream
$BinaryWriter = New-Object System.IO.BinaryWriter ( $CombinedStream )
$BinaryWriter.Write( $Payload )
$BinaryWriter.Write( $Nonce )
$BinaryWriter.Write( $CipherText )
[convert]::ToBase64String( $CombinedStream.ToArray() )
}
function New-MRNGRandomString ( $Length = 20 ) {
$SecureRandom = [Org.BouncyCastle.Security.SecureRandom]::new()
$StringBuilder = [System.Text.StringBuilder]::new()
[char[]]$AvailableChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()-_=+|[]{};:',./<>?"
for ( $i = 0; $i -lt $Length; $i ++ ) {
$RandomIndex = $SecureRandom.Next( $AvailableChars.Length - 1 )
$StringBuilder.Append( $AvailableChars[ $RandomIndex ] ) > $null
}
return $StringBuilder.ToString()
}
@reddwarf666
Copy link

reddwarf666 commented May 21, 2020

@realslacker Any idea what this could be?
I tried Powershell 7.0.1 but that did not solve the issue
I opened a issue on github for Powershell Core to see if they have any ideas:
PowerShell/PowerShell#12741

@reddwarf666
Copy link

@realslacker It's been a while now and I thought to check in and see if maybe you found a solution to the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment