C# PrivateBin API基于BouncyCastle的实现

C# PrivateBin API基于BouncyCastle的实现,c#,powershell,encryption,bouncycastle,aes-gcm,C#,Powershell,Encryption,Bouncycastle,Aes Gcm,我正在尝试使用Powershell中的BouncyCastle向PrivateBin API发送粘贴。 迄今为止的结果: 使用BouncyCastle的本地加密+解密正在工作 向不同的PrivateBin实例发送粘贴正在工作 在浏览器中打开粘贴+解密API返回的粘贴不起作用 网站要求输入密码(但未定义密码) 有人知道如何在PrivateBin的正确参数下使用BouncyCastle吗 function SimpleEncrypt { Param( [string]$s

我正在尝试使用Powershell中的BouncyCastle向PrivateBin API发送粘贴。 迄今为止的结果:

  • 使用BouncyCastle的本地加密+解密正在工作
  • 向不同的PrivateBin实例发送粘贴正在工作
  • 在浏览器中打开粘贴+解密API返回的粘贴不起作用
    • 网站要求输入密码(但未定义密码)
有人知道如何在PrivateBin的正确参数下使用BouncyCastle吗

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"

您尝试在哪里使用SimpledCrypt?我认为您的问题与格式有关。将值复制回网页时,在尝试解密之前,是否确定数据类型正确?当你尝试解密时,你是抛出了一个异常,还是解密成了一个不正确的明文,还是什么也不返回?你是对的,很抱歉错过了。我已经编辑了原始帖子。如果您声称它在没有从PasteBin/PrivateBin读取的情况下工作,那么您的问题一定与REST返回的值有关。使用本地版本和web版本并排运行测试,并比较对象。我相信BouncyCastle是块对齐的,所以请确保存在任何所需的填充,数据类型是它们应该是的,并且值都是它们应该是的(与仅本地(和工作)版本相比)。