Реализация на основе BouncyCastle для PrivateBin API - PullRequest
0 голосов
/ 17 марта 2020

Я пытаюсь использовать BouncyCastle в Powershell для отправки пасты в PrivateBin API. Результат на данный момент:

  • Работает локальное шифрование + дешифрование с помощью BouncyCastle.
  • Работает отправка вставки в различные экземпляры PrivateBin
  • Открыть вставку в браузере + Расшифровать Вставка, возвращаемая API, не работает
    • Веб-сайт запрашивает пароль (но не определен)

Кто-нибудь знает, как использовать BouncyCastle с нужными параметрами для PrivateBin?

function SimpleEncrypt {
   Param(
       [string]$secretmessage,
       [byte[]]$key,
       [byte[]]$nonSecretPayload = $null
   )
   if ([string]::IsNullOrEmpty($secretmessage)) {
       throw "Secret message Required!"
   }
   $nonSecretPayload = [byte[]]::new($null) #force set $null
   $plainText = [system.Text.encoding]::UTF8.GetBytes($secretmessage)
   $nonce = [byte[]]::new(16)
   $crypto = [System.Security.Cryptography.RNGCryptoServiceProvider]::new()
   $crypto.GetNonZeroBytes($nonce)
   $cipher = [Org.BouncyCastle.Crypto.Modes.GcmBlockCipher]::new([Org.BouncyCastle.Crypto.Engines.AesEngine]::new())
   $parameters = [Org.BouncyCastle.Crypto.Parameters.AeadParameters]::new([Org.BouncyCastle.Crypto.Parameters.KeyParameter]::new($key), 128, $nonce, $nonSecretPayload) #payload als byte!!!
   $cipher.Init($true, $parameters)
   $cipherText = [byte[]]::new($cipher.GetOutputSize($plainText.Length))
   $len = $cipher.ProcessBytes($plainText, 0, $plainText.Length, $cipherText, 0)
   $null = $cipher.DoFinal($cipherText, $len)
   $authtag = $cipher.GetMac() #auto appended using DoFinal()
   $combinedStream = [System.IO.MemoryStream]::new()
   $binaryWriter = [System.IO.BinaryWriter]::new($combinedStream)
   #$binaryWriter.Write($nonSecretPayload)
   $binaryWriter.Write($nonce)
   $binaryWriter.Write($cipherText)
   $cipherText = $combinedStream.ToArray()
   return @{
       cipherText = [convert]::ToBase64String($cipherText)
       nonce = $nonce
       mactag = $authtag
       key = $kdfkey
   }
}

function SimpleDecrypt {
   Param(
       [string]$encryptedMessage,
       [byte[]]$key,
       [int]$nonSecretPayloadLength = 0
   )
   if ([string]::IsNullOrEmpty($encryptedMessage)) {
       throw "Secret message Required!"
   }
   $encbyteMessage = [byte[]][convert]::FromBase64String($encryptedMessage)
   $cipherStream = [System.IO.MemoryStream]::new($encbyteMessage)
   $cipherReader = [System.IO.BinaryReader]::new($cipherStream)
   $nonSecretPayload = $cipherReader.ReadBytes($nonSecretPayloadLength)
   $nonce = $cipherReader.ReadBytes(16)
   $cipher = [Org.BouncyCastle.Crypto.Modes.GcmBlockCipher]::new([Org.BouncyCastle.Crypto.Engines.AesEngine]::new())
   $parameters = [Org.BouncyCastle.Crypto.Parameters.AeadParameters]::new([Org.BouncyCastle.Crypto.Parameters.KeyParameter]::new($key), $MacBitSize, $nonce, $nonSecretPayload) #payload als byte!!!
   $cipher.Init($false, $parameters)
   $cipherText = $cipherReader.ReadBytes($encbyteMessage.Length - $nonSecretPayloadLength - $nonce.Length)
   $plainText = [byte[]]::new($cipher.GetOutputSize($cipherText.Length))
   $len = $cipher.ProcessBytes($cipherText, 0, $cipherText.Length, $plainText, 0)
   $null = $cipher.DoFinal($plainText, $len)
   return [system.Text.encoding]::UTF8.GetString($plainText)
}

function PBKDF2_SHA256_GetHash {
   Param([string]$password, [byte[]]$salt, [int]$iterations, [int]$hashByteSize)
   $pdb = [Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator]::new([Org.BouncyCastle.Crypto.Digests.Sha256Digest]::new())
   $pdb.init([Org.BouncyCastle.Crypto.PbeParametersGenerator]::Pkcs5PasswordToBytes($password.ToCharArray()), $salt, $iterations)
   $key = $pdb.GenerateDerivedMacParameters($hashByteSize * 8)
   return [byte[]]$key.GetKey()
}

#example
[byte[]]$salt = [byte[]]::new(8)
$crypto = [System.Security.Cryptography.RNGCryptoServiceProvider]::new()
$crypto.GetNonZeroBytes($salt)
$kdfsaltb64encoded = [convert]::ToBase64String($salt)
$kdfkeygen = [Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator]::new([Org.BouncyCastle.Crypto.Digests.Sha256Digest]::new())
$kdfkeygen.Init("", $salt, 100000)
$kdfkeygenderivedparams = ($kdfkeygen.GenerateDerivedParameters(128))
[byte[]]$kdfkey = $kdfkeygenderivedparams.getKey()
$kdfkeyb64encoded = [convert]::ToBase64String($kdfkey)
$enc = SimpleEncrypt -secretmessage "hallo welt" -key $kdfkey
$iv = $enc.nonce
$ivb64encoded = [convert]::ToBase64String($iv)
$dec = SimpleDecrypt -key $kdfkey -encryptedMessage $enc.cipherText
$ciphertext = $enc.cipherText

$postbody = @{
   v= "2"
   adata = @(@("$ivb64encoded","$kdfsaltb64encoded",100000,256,128,"aes","gcm","none"),"plaintext",0,0)
   ct = "$($ciphertext)"
   meta = @{
       expire = "1day"
   }
}
$body = $postbody | convertto-json | out-string
$uri = "https://cpaste.org"
$header = @{"X-Requested-With" = "JSONHttpRequest"}
$response = Invoke-RestMethod -Method POST -Uri "$($uri)" -Headers $header -Body $body
$response

Моя попытка расшифровки с URL:

$header = @{"X-Requested-With" = "JSONHttpRequest"}
$decrypturl = "https://cpaste.org/?29cce083dbb9b6d8#FU4BjDSip6yv4HEmAJYzEJgwaMNxyCLih17vE4auf6vJ"
$decdata = Invoke-RestMethod -Headers $header -Uri $decrypturl -method get
$iv = [convert]::FromBase64String($decdata.adata[0][0])
$salt = [convert]::FromBase64String($decdata.adata[0][1])
$key = PBKDF2_SHA256_GetHash -salt $salt -iterations 100000 -hashByteSize 16
SimpleDecrypt -key $key -encryptedMessage $decdata.ct

$ciphertexttag = [convert]::FromBase64String($decdata.ct)

и соответствующее сообщение об ошибке:

..."DoFinal" mit 2 Argument(en):  "mac check in GCM failed"
...