2016-03-21 1 views
3

Selon MSDN, il est une pratique recommandée inclure à la fois les clés publiques et privées utilisées pour les assemblées forte dénomination dans le système de contrôle de source publique si vous développez des logiciels open-source:Pourquoi est-il recommandé d'inclure la clé privée utilisée pour la signature d'assembly dans les référentiels open-source?

Si vous êtes un développeur open source et vous voulez les avantages d'identité d'un assembly nommé fort, pensez à vérifier dans la clé privée associée à un assembly dans votre système de contrôle de source.

Ceci est quelque chose qui me rend très confus. Rendre la clé privée publique? L'objectif et la sécurité de la cryptographie asymétrique ne seraient-ils pas vaincus dans ce cas?

Je vois dans le même article cette note:

Ne comptez pas sur des noms forts pour la sécurité. Ils fournissent une identité unique seulement.

Cela n'aide pas à réduire ma confusion. Pourquoi alors utiliser une paire de clés privée-publique si la sécurité n'est pas le but? Le mécanisme de dénomination forte dans .NET utilise-t-il de manière inappropriée des paires de clés privées-publiques? Ma conjecture est que je suis manquant ou malentendu quelque chose.

Répondre

3

La signature d'un nom fort n'est pas pour des raisons de sécurité, mais pour garantir l'unicité. Il en est ainsi si deux personnes font vous avez une façon de les différencier dans le GAC. Si vous disposez d'une bibliothèque open source et que vous souhaitez que le MyOpenSource.dll v1.0.0.0 de votre utilisateur final puisse être utilisé en remplacement du MyOpenSource.dll v1.0.0.0 publié, la copie de l'utilisateur et la copie officielle doivent toutes deux être signées avec la même clé (ou les deux ne doivent pas être signés du tout). C'est pourquoi vous voudriez le distribuer.

La clé de nom fort n'est pas pour dire "Ceci est une copie officielle, non modifiée de MyOpenSource.dll", c'est ce que Authenticode signing est pour. C'est seulement pour prévenir les collisions de noms de différents éditeurs.

+0

Donc, il n'y a pas de mal à publier cette clé privée aussi longtemps qu'elle est utilisée et uniquement pour la signature de cet assembly particulier? Ou, pour le dire autrement, si Microsoft décidait d'ouvrir toutes ses bibliothèques de classes .NET sur GitHub, inclurait-il aussi le fichier .snk utilisé pour signer ces assemblées? –

+1

S'ils voulaient permettre aux gens de remplacer les assemblées officielles par leurs propres copies dans le GAC, oui. Et en ce qui concerne les dommages, tant que la clé privée n'est utilisée que pour la signature forte, il est bon de la distribuer. Si vous utilisez également la même clé pour authentifier la signature, il y a un risque certain (mais il n'y a aucune raison de ne pas utiliser deux clés séparées) –

+0

C'est un peu plus clair maintenant, mais je dirais quand même qu'une fois cette clé privée public, vous ne pouvez même plus garantir l'unicité. N'importe qui dans le monde peut maintenant créer un assembly avec exactement le même nom fort. Vous perdez tous les avantages que vous aviez quand il est resté privé. Même Jeffrey Richter dans "CLR via C#" dit que les clés privées utilisées dans la signature des assemblages devraient être stockées sur des dispositifs sécurisés et jamais partagées entre les entreprises. –

0

Je ne suis pas d'accord que la signature de vos assemblys n'a aucune part dans la sécurité. Oui, il est utilisé pour identifier un assemblage. Et par défaut, la signature n'est pas appliquée. Donc à cet égard, oui, la sécurité n'est pas directement affectée uniquement par la signature. Cependant, vous pouvez utiliser votre paire de clés pour appliquer la vérification de la signature sans avoir besoin de vous procurer un certificat d'autorité de certification. Pour ce faire, mais vous devez P/Invoke cette fonction:

Imports System.Runtime.InteropServices 

Friend Class NativeMethods 
    <DllImport("mscoree.dll", CharSet:=CharSet.Unicode)> _ 
    Public Shared Function StrongNameSignatureVerificationEx(wszFilePath As String, fForceVerification As Byte, ByRef pfWasVerified As Byte) As Boolean 
    End Function 
End Class 

À partir de là, concevoir une classe de base que vos ensembles protégés peuvent hériter de:

Imports System.Reflection 
Imports System.Security.Cryptography 

Public Class SignedClassBase 
    Shared Sub New() 
     VerifyAssemblySignature(Assembly.GetCallingAssembly()) 
    End Sub 

    Public Sub New() 
     VerifyAssemblySignature(Assembly.GetCallingAssembly()) 
    End Sub 

    Private Shared Sub VerifyAssemblySignature(assembly As Assembly) 
     Dim wasVerified As Boolean 
     If Not (NativeMethods.StrongNameSignatureVerificationEx(assembly.Location, True, wasVerified) AndAlso wasVerified) Then 
      Throw New CryptographicException("Verification failed: Assembly signature did not match.") 
     End If 
    End Sub 
End Class 

Et puis appeler le constructeur de base de votre dérivée classe:

Public Class Utils 
    Inherits SignedClassBase 

    Shared Sub New() 
     RuntimeHelpers.RunClassConstructor(GetType(SignedClassBase).TypeHandle) 
    End Sub 

    Public Sub New() 
     MyBase.New() 
    End Sub 
End Class 

maintenant, si un ensemble modifié est instancié, un CryptographicException jetteront du constructeur de la classe de base, ce qui empêche la classe dérivée d'être utilisée. Alors que la signature de code seule n'est pas directement liée à la sécurité, l'application de la signature de l'assemblage peut certainement ajouter à la sécurité que vous avez déjà en place, en conjonction avec une obfuscation forte si nécessaire. À cet égard, la clé privée DOIT rester secrète.Le partage de la clé privée dans un projet open-source est simplement un moyen de faciliter la vie des développeurs impliqués. Il serait BEAUCOUP meilleur de signer à la place les assemblages dans le cadre du processus de construction officiel, et de garder votre clé privée complètement secrète. Sinon, n'importe qui peut recompiler un assembly avec un code potentiellement malveillant et le signer avec votre clé privée, et distribuer des copies corrompues de votre projet.

+0

Je suis content que nous soyons d'accord sur l'importance de garder la clé privée privée. En ce qui concerne l'exemple de code, il m'a fallu un peu de traduire mentalement VB.NET en C# car je suis beaucoup plus familier avec ce dernier, mais je ne suis pas sûr de comprendre où et quand le constructeur Utils doit être appelé. –

+0

Vous n'avez pas besoin d'appeler le constructeur de la classe dérivée, il est appelé par tout ce qui l'appelle. La première fois que vous invoquez une méthode shared (ou static in C#, mes excuses je n'ai pas vu la balise C# origin) dans la classe Utils, son constructeur partagé est appelé, ce qui appelle le constructeur de la classe de base. Et si vous "var bleh = new Utils();", le constructeur public est appelé, et de nouveau le constructeur de la classe de base est exécuté. –