Как я могу экспортировать вычисленную подпись в файл?

#powershell #cryptography #bouncycastle #gost3410

Вопрос:

Я использую bouncycastle 1.8.8. Я пытаюсь вычислить необработанную подпись и экспортировать ее в файл. После экспорта необработанной подписи я пытаюсь скопировать ее и проверить импортированную необработанную подпись. После импорта необработанной подписи и ее проверки я иногда получаю $true, а иногда $false… Не могли бы вы сказать мне, пожалуйста, как я должен экспортировать НЕОБРАБОТАННУЮ подпись в файл, а затем импортировать ее и проверить ее?

Это мой код:

 Add-Type -Path "..LibBouncyCastle.dll"
$ProjectPath = (gi '..').FullName

function ComputeHash {
    param (
        [parameter(Mandatory=$true)][System.String] $Path
    )

    [void]([byte[]] $DataFileRawBytes = (gci -Path $Path | % {[System.IO.File]::ReadAllBytes($_.FullName)}) -as [byte[]]);
    [void]([Org.BouncyCastle.Crypto.Digests.Gost3411_2012_256Digest] $Gost3411_2012_256Digest = [Org.BouncyCastle.Crypto.Digests.Gost3411_2012_256Digest]::new());
    [void]([byte[]] $HashCode = [byte[]]::new(32));
    [void]($Gost3411_2012_256Digest.BlockUpdate($DataFileRawBytes, 0, $DataFileRawBytes.Length));
    [void]($Gost3411_2012_256Digest.DoFinal($HashCode, 0));
    [void]($Gost3411_2012_256Digest.Reset());
    return $HashCode;
}

function Write-Keys {
    param (
        [parameter(Mandatory=$true)] $KeyPair,
        [parameter(Mandatory=$true)][System.String] $Path,
        [parameter(Mandatory=$true)][System.String] $KeyVis
    )
    if ($KeyVis -eq "prk") {
        [System.IO.TextWriter] $tw = [System.IO.File]::CreateText($Path   "prk.pem");
    }
    elseif ($KeyVis -eq "pbk") {
        [System.IO.TextWriter] $tw = [System.IO.File]::CreateText($Path   "pbk.pem");
    }
    $pw = [Org.BouncyCastle.OpenSsl.PemWriter]::new($tw);
    $pw.WriteObject($KeyPair);
    $tw.Flush();
    $tw.Close();
    $tw.Dispose();
}

function Read-Keys {
    param (
        [parameter(Mandatory=$true)][System.String] $Path,
        [parameter(Mandatory=$true)][System.String] $KeyVis
    )
    if ($KeyVis -eq "prk") {
        [System.IO.TextReader] $tr = [System.IO.File]::OpenText($Path   "prk.pem")
    }
    elseif ($KeyVis -eq "pbk") {
        [System.IO.TextReader] $tr = [System.IO.File]::OpenText($Path   "pbk.pem")
    }
    $pr = [Org.BouncyCastle.OpenSsl.PemReader]::new($tr);
    $KeyPair = $pr.ReadObject();
    $tr.Close();
    $tr.Dispose();
    return $KeyPair
}

function Write-Signature {
    param (
        [parameter(Mandatory=$true)] $Signature,
        [parameter(Mandatory=$true)][System.String] $Path
    )
    [System.IO.File]::WriteAllBytes($Path   "signature.pem", ($Signature[0].ToByteArrayUnsigned()   $Signature[1].ToByteArrayUnsigned()))

}

function Read-Signature {
    param (
        [parameter(Mandatory=$true)][System.String] $Path
    )
    
    $Full = [System.IO.File]::ReadAllBytes($Path   "signature.pem");
    $Signature = [Org.BouncyCastle.Math.BigInteger]::new($Full[0..31] -as [byte[]]), [Org.BouncyCastle.Math.BigInteger]::new($Full[32..63] -as [byte[]])
    return $Signature;
}

function Test-Export-Keys-And-Signature {
    param (
        [parameter(Mandatory=$false)][System.Int16] $KeyLength = 512,
        [parameter(Mandatory=$false)][System.String] $Path
    )

    [byte[]] $HashCode = ComputeHash -Path ($Path   "to_be_signedto_be_signed.txt");
    $secureRandom = [Org.BouncyCastle.Security.SecureRandom]::new();
    $curve = [Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves]::GetByName("GostR3410-2001-CryptoPro-A")
    $dp = [Org.BouncyCastle.Crypto.Parameters.ECDomainParameters]::new($curve.curve, $curve.g, $curve.n, $curve.h, $curve.GetSeed())
    $ECGost3410Parameters = [Org.BouncyCastle.Crypto.Parameters.ECGost3410Parameters]::new($dp, "1.2.643.2.2.36.0", "1.2.643.7.1.1.2.2", $null)
    $ECKeyGenerationParameters = [Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters]::new($ECGost3410Parameters, $secureRandom);
    $generator = [Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator]::new();
    $generator.Init($ECKeyGenerationParameters);
    $KeyPair = $generator.GenerateKeyPair();
    
    [Org.BouncyCastle.Crypto.Signers.ECGost3410Signer] $ECGost3410Signer = [Org.BouncyCastle.Crypto.Signers.ECGost3410Signer]::new();
    $ParametersWithRandom = [Org.BouncyCastle.Crypto.Parameters.ParametersWithRandom]::new($KeyPair.Private, $secureRandom);
    $ECGost3410Signer.Init($true, $ParametersWithRandom);

    $Signature = $ECGost3410Signer.GenerateSignature($HashCode); #Compute RAW-signature    
    Write-Signature -Signature $Signature -Path ($Path   "sig"); #Export RAW-signature
    $Signature_2 = Read-Signature -Path ($Path   "sig"); #Import RAW-signature
    $ECGost3410Signer.Init($false, $KeyPair.Public);
    $ECGost3410Signer.VerifySignature($HashCode, $Signature_2[0], $Signature_2[1]); #Verify imported RAW-signature: sometimes get $true, sometimes get $false 

    Write-Keys -KeyPair $KeyPair.Private -Path ($Path   "keys") -KeyVis "prk" #Export private key
    Write-Keys -KeyPair $KeyPair.Public -Path ($Path   "keys") -KeyVis "pbk" #Export public key

    $Pbk = Read-Keys -Path ($Path   "keys") -KeyVis "pbk" #Import public key
    $Prk = Read-Keys -Path ($Path   "keys") -KeyVis "prk" #Import private key
    $ParametersWithRandom = [Org.BouncyCastle.Crypto.Parameters.ParametersWithRandom]::new($Prk, $secureRandom);
    $ECGost3410Signer.Init($true, $ParametersWithRandom);
    $Signature = $ECGost3410Signer.GenerateSignature($HashCode);
    $ECGost3410Signer.Init($false, $Pbk);
    $ECGost3410Signer.VerifySignature($HashCode, $Signature[0], $Signature[1]); #Verify non-exported RAW-signature with imported public key. Always get $true
}

Test-Export-Keys-And-Signature -Path $ProjectPath