about summary refs log tree commit diff
path: root/perl/lib
diff options
context:
space:
mode:
Diffstat (limited to 'perl/lib')
-rw-r--r--perl/lib/Nix/Config.pm.in27
-rw-r--r--perl/lib/Nix/Crypto.pm42
-rw-r--r--perl/lib/Nix/Manifest.pm19
-rw-r--r--perl/lib/Nix/Store.pm1
-rw-r--r--perl/lib/Nix/Store.xs40
5 files changed, 68 insertions, 61 deletions
diff --git a/perl/lib/Nix/Config.pm.in b/perl/lib/Nix/Config.pm.in
index bc51310e5aff..388acd2e61c0 100644
--- a/perl/lib/Nix/Config.pm.in
+++ b/perl/lib/Nix/Config.pm.in
@@ -1,5 +1,7 @@
 package Nix::Config;
 
+use MIME::Base64;
+
 $version = "@PACKAGE_VERSION@";
 
 $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
@@ -19,24 +21,31 @@ $useBindings = "@perlbindings@" eq "yes";
 
 %config = ();
 
+%binaryCachePublicKeys = ();
+
 sub readConfig {
     if (defined $ENV{'_NIX_OPTIONS'}) {
         foreach my $s (split '\n', $ENV{'_NIX_OPTIONS'}) {
             my ($n, $v) = split '=', $s, 2;
             $config{$n} = $v;
         }
-        return;
+    } else {
+        my $config = "$confDir/nix.conf";
+        return unless -f $config;
+
+        open CONFIG, "<$config" or die "cannot open ‘$config’";
+        while (<CONFIG>) {
+            /^\s*([\w\-\.]+)\s*=\s*(.*)$/ or next;
+            $config{$1} = $2;
+        }
+        close CONFIG;
     }
 
-    my $config = "$confDir/nix.conf";
-    return unless -f $config;
-
-    open CONFIG, "<$config" or die "cannot open ‘$config’";
-    while (<CONFIG>) {
-        /^\s*([\w\-\.]+)\s*=\s*(.*)$/ or next;
-        $config{$1} = $2;
+    foreach my $s (split(/ /, $config{"binary-cache-public-keys"} // "")) {
+        my ($keyName, $publicKey) = split ":", $s;
+        next unless defined $keyName && defined $publicKey;
+        $binaryCachePublicKeys{$keyName} = decode_base64($publicKey);
     }
-    close CONFIG;
 }
 
 return 1;
diff --git a/perl/lib/Nix/Crypto.pm b/perl/lib/Nix/Crypto.pm
deleted file mode 100644
index 0286e88d3d28..000000000000
--- a/perl/lib/Nix/Crypto.pm
+++ /dev/null
@@ -1,42 +0,0 @@
-package Nix::Crypto;
-
-use strict;
-use MIME::Base64;
-use Nix::Store;
-use Nix::Config;
-use IPC::Open2;
-
-our @ISA = qw(Exporter);
-our @EXPORT = qw(signString isValidSignature);
-
-sub signString {
-    my ($privateKeyFile, $s) = @_;
-    my $hash = hashString("sha256", 0, $s);
-    my ($from, $to);
-    my $pid = open2($from, $to, $Nix::Config::openssl, "rsautl", "-sign", "-inkey", $privateKeyFile);
-    print $to $hash;
-    close $to;
-    local $/ = undef;
-    my $sig = <$from>;
-    close $from;
-    waitpid($pid, 0);
-    die "$0: OpenSSL returned exit code $? while signing hash\n" if $? != 0;
-    my $sig64 = encode_base64($sig, "");
-    return $sig64;
-}
-
-sub isValidSignature {
-    my ($publicKeyFile, $sig64, $s) = @_;
-    my ($from, $to);
-    my $pid = open2($from, $to, $Nix::Config::openssl, "rsautl", "-verify", "-inkey", $publicKeyFile, "-pubin");
-    print $to decode_base64($sig64);
-    close $to;
-    my $decoded = <$from>;
-    close $from;
-    waitpid($pid, 0);
-    return 0 if $? != 0;
-    my $hash = hashString("sha256", 0, $s);
-    return $decoded eq $hash;
-}
-
-1;
diff --git a/perl/lib/Nix/Manifest.pm b/perl/lib/Nix/Manifest.pm
index 9b7e89fa42fb..ec3e48fcfbec 100644
--- a/perl/lib/Nix/Manifest.pm
+++ b/perl/lib/Nix/Manifest.pm
@@ -8,8 +8,9 @@ use Cwd;
 use File::stat;
 use File::Path;
 use Fcntl ':flock';
+use MIME::Base64;
 use Nix::Config;
-use Nix::Crypto;
+use Nix::Store;
 
 our @ISA = qw(Exporter);
 our @EXPORT = qw(readManifest writeManifest updateManifestDB addPatch deleteOldManifests parseNARInfo);
@@ -440,22 +441,20 @@ sub parseNARInfo {
         }
         my ($sigVersion, $keyName, $sig64) = split ";", $sig;
         $sigVersion //= 0;
-        if ($sigVersion != 1) {
+        if ($sigVersion != 2) {
             warn "NAR info file ‘$location’ has unsupported version $sigVersion; ignoring\n";
             return undef;
         }
         return undef unless defined $keyName && defined $sig64;
-        my $publicKeyFile = $Nix::Config::config{"binary-cache-public-key-$keyName"};
-        if (!defined $publicKeyFile) {
+
+        my $publicKey = $Nix::Config::binaryCachePublicKeys{$keyName};
+        if (!defined $publicKey) {
             warn "NAR info file ‘$location’ is signed by unknown key ‘$keyName’; ignoring\n";
             return undef;
         }
-        if (! -f $publicKeyFile) {
-            die "binary cache public key file ‘$publicKeyFile’ does not exist\n";
-            return undef;
-        }
-        if (!isValidSignature($publicKeyFile, $sig64, $signedData)) {
-            warn "NAR info file ‘$location’ has an invalid signature; ignoring\n";
+
+        if (!checkSignature($publicKey, decode_base64($sig64), $signedData)) {
+            warn "NAR info file ‘$location’ has an incorrect signature; ignoring\n";
             return undef;
         }
         $res->{signedBy} = $keyName;
diff --git a/perl/lib/Nix/Store.pm b/perl/lib/Nix/Store.pm
index 89cfaefa5fd4..233a432ee085 100644
--- a/perl/lib/Nix/Store.pm
+++ b/perl/lib/Nix/Store.pm
@@ -17,6 +17,7 @@ our @EXPORT = qw(
     queryPathFromHashPart
     topoSortPaths computeFSClosure followLinksToStorePath exportPaths importPaths
     hashPath hashFile hashString
+    signString checkSignature
     addToStore makeFixedOutputPath
     derivationFromPath
 );
diff --git a/perl/lib/Nix/Store.xs b/perl/lib/Nix/Store.xs
index ff90616d3766..792d2f649935 100644
--- a/perl/lib/Nix/Store.xs
+++ b/perl/lib/Nix/Store.xs
@@ -11,6 +11,8 @@
 #include <misc.hh>
 #include <util.hh>
 
+#include <sodium.h>
+
 
 using namespace nix;
 
@@ -223,6 +225,44 @@ SV * hashString(char * algo, int base32, char * s)
         }
 
 
+SV * signString(SV * secretKey_, char * msg)
+    PPCODE:
+        try {
+            STRLEN secretKeyLen;
+            unsigned char * secretKey = (unsigned char *) SvPV(secretKey_, secretKeyLen);
+            if (secretKeyLen != crypto_sign_SECRETKEYBYTES)
+                throw Error("secret key is not valid");
+
+            unsigned char sig[crypto_sign_BYTES];
+            unsigned long long sigLen;
+            crypto_sign_detached(sig, &sigLen, (unsigned char *) msg, strlen(msg), secretKey);
+            XPUSHs(sv_2mortal(newSVpv((char *) sig, sigLen)));
+        } catch (Error & e) {
+            croak(e.what());
+        }
+
+
+int checkSignature(SV * publicKey_, SV * sig_, char * msg)
+    CODE:
+        try {
+            STRLEN publicKeyLen;
+            unsigned char * publicKey = (unsigned char *) SvPV(publicKey_, publicKeyLen);
+            if (publicKeyLen != crypto_sign_PUBLICKEYBYTES)
+                throw Error("public key is not valid");
+
+            STRLEN sigLen;
+            unsigned char * sig = (unsigned char *) SvPV(sig_, sigLen);
+            if (sigLen != crypto_sign_BYTES)
+                throw Error("signature is not valid");
+
+            RETVAL = crypto_sign_verify_detached(sig, (unsigned char *) msg, strlen(msg), publicKey) == 0;
+        } catch (Error & e) {
+            croak(e.what());
+        }
+    OUTPUT:
+        RETVAL
+
+
 SV * addToStore(char * srcPath, int recursive, char * algo)
     PPCODE:
         try {