Skip to content

Commit 5e142d1

Browse files
Fix PR #45 review findings: init guards, validation consistency, and net8-compatible interop build
1 parent b457c6d commit 5e142d1

11 files changed

Lines changed: 51 additions & 31 deletions

File tree

PSModule/Sodium.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net10.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<AssemblyName>PSModule.Sodium</AssemblyName>
66
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="System.Management.Automation" Version="7.6.1" PrivateAssets="All" />
10+
<PackageReference Include="System.Management.Automation" Version="7.4.7" PrivateAssets="All" />
1111
<PackageReference Include="libsodium" Version="1.0.22" />
1212
</ItemGroup>
1313

PSModule/Sodium/Sodium.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,18 @@ public static string SealBase64(string plaintext, string publicKeyBase64)
228228
var publicKey = DecodeBase64Exact(publicKeyBase64, PublicKeyBytes, "public key");
229229
var message = Encoding.UTF8.GetBytes(plaintext);
230230
var ciphertext = new byte[message.Length + SealBytes];
231-
if (Native.crypto_box_seal(ciphertext, message, (ulong)message.LongLength, publicKey) != 0)
231+
try
232+
{
233+
if (Native.crypto_box_seal(ciphertext, message, (ulong)message.LongLength, publicKey) != 0)
234+
{
235+
throw new InvalidOperationException("Encryption failed.");
236+
}
237+
return Convert.ToBase64String(ciphertext);
238+
}
239+
finally
232240
{
233-
throw new InvalidOperationException("Encryption failed.");
241+
CryptographicOperations.ZeroMemory(message);
234242
}
235-
return Convert.ToBase64String(ciphertext);
236243
}
237244

238245
public static string OpenSealBase64(string ciphertextBase64, string privateKeyBase64)
@@ -253,7 +260,7 @@ private static string OpenSealBase64Core(string ciphertextBase64, string private
253260
var ciphertext = Convert.FromBase64String(ciphertextBase64);
254261
if (ciphertext.Length < SealBytes)
255262
{
256-
throw new InvalidOperationException($"Invalid sealed box. Expected at least {SealBytes} bytes but got {ciphertext.Length}.");
263+
throw new ArgumentException($"Invalid sealed box. Expected at least {SealBytes} bytes but got {ciphertext.Length}.");
257264
}
258265
var privateKey = DecodeBase64Exact(privateKeyBase64, SecretKeyBytes, "private key");
259266
var publicKey = new byte[PublicKeyBytes];
@@ -291,7 +298,7 @@ private static byte[] DecodeBase64Exact(string value, int expectedLength, string
291298
var bytes = Convert.FromBase64String(value);
292299
if (bytes.Length != expectedLength)
293300
{
294-
throw new InvalidOperationException($"Invalid {label}. Expected {expectedLength} bytes but got {bytes.Length}.");
301+
throw new ArgumentException($"Invalid {label}. Expected {expectedLength} bytes but got {bytes.Length}.");
295302
}
296303
return bytes;
297304
}

PSModule/build.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ try {
1919
throw "dotnet publish failed for runtime '$_'."
2020
}
2121

22-
$source = "$PSScriptRoot/bin/Release/net10.0/$_/publish"
22+
$source = "$PSScriptRoot/bin/Release/net8.0/$_/publish"
2323
$destination = "$PSScriptRoot/../src/libs/$_"
2424
Copy-Item -Path $source -Destination $destination -Recurse -Force
2525
}

src/functions/private/Initialize-Sodium.ps1

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@
2222
try {
2323
$initializationResult = [PSModule.Sodium]::sodium_init()
2424
} catch {
25+
$script:Supported = $false
2526
if ($IsWindows) {
26-
$script:Supported = Assert-VisualCRedistributableInstalled -Version '14.0' -Architecture $script:ProcessArchitecture
27+
if ($script:ProcessArchitecture -in @('X64', 'X86')) {
28+
$hasRuntime = Assert-VisualCRedistributableInstalled -Version '14.0' -Architecture $script:ProcessArchitecture
29+
if (-not $hasRuntime) {
30+
throw "Sodium native initialization failed; the Visual C++ Redistributable for $($script:ProcessArchitecture) appears to be missing or below the required version."
31+
}
32+
}
2733
}
2834
throw
2935
}

src/functions/public/ConvertFrom-SodiumSealedBox.ps1

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,13 @@
6868
[string] $PrivateKey
6969
)
7070

71-
begin {}
71+
begin {
72+
Initialize-Sodium
73+
}
7274

7375
process {
7476
try {
75-
if ($PublicKey) {
77+
if (-not [string]::IsNullOrWhiteSpace($PublicKey)) {
7678
return [PSModule.Sodium]::OpenSealBase64($SealedBox, $PrivateKey, $PublicKey)
7779
}
7880
return [PSModule.Sodium]::OpenSealBase64($SealedBox, $PrivateKey)

src/functions/public/ConvertTo-SodiumSealedBox.ps1

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@
5555
[ValidateNotNullOrEmpty()]
5656
[string] $PublicKey
5757
)
58-
begin {}
58+
begin {
59+
Initialize-Sodium
60+
}
5961

6062
process {
6163
try {

src/functions/public/Get-SodiumPublicKey.ps1

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,24 +81,16 @@
8181
[switch] $AsByteArray
8282
)
8383

84-
begin {}
84+
begin {
85+
Initialize-Sodium
86+
}
8587

8688
process {
8789
if ($AsByteArray) {
88-
$privateKeyByteArray = $null
8990
try {
90-
$publicKeyByteArray = [byte[]]::new($script:SodiumPublicKeyBytes)
91-
$privateKeyByteArray = [System.Convert]::FromBase64String($PrivateKey)
92-
if ($privateKeyByteArray.Length -ne $script:SodiumPrivateKeyBytes) {
93-
throw "Invalid private key. Expected $script:SodiumPrivateKeyBytes bytes but got $($privateKeyByteArray.Length)."
94-
}
95-
$deriveResult = [PSModule.Sodium]::crypto_scalarmult_base($publicKeyByteArray, $privateKeyByteArray)
96-
if ($deriveResult -ne 0) { throw 'Unable to derive public key from private key.' }
97-
return $publicKeyByteArray
98-
} finally {
99-
if ($null -ne $privateKeyByteArray -and $privateKeyByteArray.Length -gt 0) {
100-
[array]::Clear($privateKeyByteArray, 0, $privateKeyByteArray.Length)
101-
}
91+
return [System.Convert]::FromBase64String([PSModule.Sodium]::DerivePublicKeyBase64($PrivateKey))
92+
} catch [System.Management.Automation.MethodInvocationException] {
93+
throw $_.Exception.InnerException
10294
}
10395
}
10496
try {

src/functions/public/New-SodiumKeyPair.ps1

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,13 @@
8080
ParameterSetName = 'SeededKeyPair',
8181
ValueFromPipeline
8282
)]
83-
[ValidateNotNullOrEmpty()]
83+
[AllowEmptyString()]
8484
[string] $Seed
8585
)
8686

87-
begin {}
87+
begin {
88+
Initialize-Sodium
89+
}
8890

8991
process {
9092
try {

src/main.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ switch ($true) {
3636
$assemblyPath = Join-Path -Path $PSScriptRoot -ChildPath "libs/$runtimeIdentifier/PSModule.Sodium.dll"
3737
Import-Module $assemblyPath -ErrorAction Stop
3838

39-
# Optimistically mark supported; Initialize-Sodium will run the Windows VC++ runtime check lazily only if native init fails.
39+
# Optimistically mark supported; Initialize-Sodium runs during module import and checks Windows VC++ runtime only if native init fails.
4040
$script:Supported = $true
4141
$script:ProcessArchitecture = $processArchitecture.ToString()
4242

src/variables/private/Initialized.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
$script:SodiumPublicKeyBytes = $null
33
$script:SodiumPrivateKeyBytes = $null
44
$script:SodiumSealBytes = $null
5+
$script:SodiumSeedBytes = $null

0 commit comments

Comments
 (0)