diff --git a/src/Compiler/AbstractIL/ilsign.fs b/src/Compiler/AbstractIL/ilsign.fs index 53add630789..d88b799d030 100644 --- a/src/Compiler/AbstractIL/ilsign.fs +++ b/src/Compiler/AbstractIL/ilsign.fs @@ -300,20 +300,7 @@ let signStream stream keyBlob = let signature = createSignature hash keyBlob KeyType.KeyPair patchSignature stream peReader signature -let signatureSize (pk: byte array) = - if pk.Length < 25 then - raise (CryptographicException(getResourceString (FSComp.SR.ilSignInvalidPKBlob ()))) - let mutable reader = BlobReader pk - reader.ReadBigInteger 12 |> ignore // Skip CLRHeader - reader.ReadBigInteger 8 |> ignore // Skip BlobHeader - let magic = reader.ReadInt32() // Read magic - - if not (magic = RSA_PRIV_MAGIC || magic = RSA_PUB_MAGIC) then // RSAPubKey.magic - raise (CryptographicException(getResourceString (FSComp.SR.ilSignInvalidPKBlob ()))) - - let x = reader.ReadInt32() / 8 - x // Returns a CLR Format Blob public key let getPublicKeyForKeyPair keyBlob = @@ -330,65 +317,84 @@ type pubkeyOptions = byte array * bool let signerGetPublicKeyForKeyPair (kp: keyPair) : pubkey = getPublicKeyForKeyPair kp -let signerSignatureSize (pk: pubkey) : int = signatureSize pk let signerSignStreamWithKeyPair stream keyBlob = signStream stream keyBlob let failWithContainerSigningUnsupportedOnThisPlatform () = failwith (FSComp.SR.containerSigningUnsupportedOnThisPlatform () |> snd) +let signerGetPublicKeyForKeyContainer (_: keyContainerName) : pubkey = + failWithContainerSigningUnsupportedOnThisPlatform () + +let signerSignStreamWithKeyContainer (_: Stream) (_: keyContainerName) = + failWithContainerSigningUnsupportedOnThisPlatform () + //--------------------------------------------------------------------- // Strong name signing //--------------------------------------------------------------------- -type ILStrongNameSigner = - | PublicKeySigner of pubkey - | PublicKeyOptionsSigner of pubkeyOptions - | KeyPair of keyPair - | KeyContainer of keyContainerName +type internal SignerData = + | PublicKeySigner of byte array + | PublicKeyOptionsSigner of byte array * bool + | KeyPair of byte array * bool + | KeyContainer of string * bool + +[] +type ILStrongNameSigner private (data: SignerData) = - static member OpenPublicKeyOptions kp p = PublicKeyOptionsSigner(kp, p) + static member OpenPublicKeyOptions (pk, p) = + ILStrongNameSigner(PublicKeyOptionsSigner(pk, p)) - static member OpenPublicKey bytes = PublicKeySigner bytes - static member OpenKeyPairFile bytes = KeyPair(bytes) - static member OpenKeyContainer s = KeyContainer s + static member ExtractPublicKey bytes = + signerGetPublicKeyForKeyPair bytes - member s.IsFullySigned = - match s with + static member OpenPublicKey bytes = + ILStrongNameSigner(PublicKeySigner bytes) + + static member OpenKeyPairFile (bytes, ?usePublicSign) = + let ups = defaultArg usePublicSign false + ILStrongNameSigner(KeyPair(bytes, ups)) + + static member OpenKeyContainer (s, ?usePublicSign) = + let ups = defaultArg usePublicSign false + ILStrongNameSigner(KeyContainer(s, ups)) + + member _.IsFullySigned = + match data with | PublicKeySigner _ -> false - | PublicKeyOptionsSigner pko -> - let _, usePublicSign = pko - usePublicSign - | KeyPair _ -> true - | KeyContainer _ -> failWithContainerSigningUnsupportedOnThisPlatform () - - member s.PublicKey = - match s with + | PublicKeyOptionsSigner (_, usePublicSign) -> not usePublicSign + | KeyPair (_, usePublicSign) -> not usePublicSign + | KeyContainer (_, usePublicSign) -> not usePublicSign + + member _.PublicKey = + match data with | PublicKeySigner pk -> pk - | PublicKeyOptionsSigner pko -> - let pk, _ = pko - pk - | KeyPair kp -> signerGetPublicKeyForKeyPair kp - | KeyContainer _ -> failWithContainerSigningUnsupportedOnThisPlatform () - - member s.SignatureSize = - let pkSignatureSize pk = - try - signerSignatureSize pk - with exn -> - failwith ("A call to StrongNameSignatureSize failed (" + exn.Message + ")") - 0x80 - - match s with - | PublicKeySigner pk -> pkSignatureSize pk - | PublicKeyOptionsSigner pko -> - let pk, _ = pko - pkSignatureSize pk - | KeyPair kp -> pkSignatureSize (signerGetPublicKeyForKeyPair kp) - | KeyContainer _ -> failWithContainerSigningUnsupportedOnThisPlatform () - - member s.SignStream stream = - match s with - | PublicKeySigner _ -> () - | PublicKeyOptionsSigner _ -> () - | KeyPair kp -> signerSignStreamWithKeyPair stream kp - | KeyContainer _ -> failWithContainerSigningUnsupportedOnThisPlatform () + | PublicKeyOptionsSigner (pk, _) -> pk + | KeyPair (kp, _) -> signerGetPublicKeyForKeyPair kp + | KeyContainer (kc, _) -> signerGetPublicKeyForKeyContainer kc + + member _.SignatureSize = + let calculateFromRaw (pk: byte array) = + if pk = null || pk.Length < 25 then 128 + else + try + let bitLen = + int pk.[12] + ||| (int pk.[13] <<< 8) + ||| (int pk.[14] <<< 16) + ||| (int pk.[15] <<< 24) + + if bitLen > 0 && bitLen % 8 = 0 then bitLen / 8 + else 128 + with _ -> 128 + + match data with + | PublicKeySigner pk + | PublicKeyOptionsSigner (pk, _) -> calculateFromRaw pk + | KeyPair (kp, _) -> calculateFromRaw kp + | KeyContainer (kc, _) -> calculateFromRaw (signerGetPublicKeyForKeyContainer kc) + + member _.SignStream stream = + match data with + | KeyPair (kp, false) -> signerSignStreamWithKeyPair stream kp + | KeyContainer (kc, false) -> signerSignStreamWithKeyContainer stream kc + | _ -> () diff --git a/src/Compiler/AbstractIL/ilsign.fsi b/src/Compiler/AbstractIL/ilsign.fsi index 588f83f84b4..badd1e4a6cc 100644 --- a/src/Compiler/AbstractIL/ilsign.fsi +++ b/src/Compiler/AbstractIL/ilsign.fsi @@ -14,12 +14,12 @@ open System.IO //--------------------------------------------------------------------- [] type ILStrongNameSigner = - member PublicKey: byte array - static member OpenPublicKeyOptions: byte array -> bool -> ILStrongNameSigner + static member OpenPublicKeyOptions: byte array * bool -> ILStrongNameSigner static member OpenPublicKey: byte array -> ILStrongNameSigner - static member OpenKeyPairFile: byte array -> ILStrongNameSigner - static member OpenKeyContainer: string -> ILStrongNameSigner + static member OpenKeyPairFile: byte array * ?usePublicSign: bool -> ILStrongNameSigner + static member OpenKeyContainer: string * ?usePublicSign: bool -> ILStrongNameSigner + static member ExtractPublicKey: byte array -> byte array member IsFullySigned: bool member PublicKey: byte array member SignatureSize: int - member SignStream: Stream -> unit + member SignStream: System.IO.Stream -> unit diff --git a/src/Compiler/Driver/CreateILModule.fs b/src/Compiler/Driver/CreateILModule.fs index 67d7861c81f..c4d28331931 100644 --- a/src/Compiler/Driver/CreateILModule.fs +++ b/src/Compiler/Driver/CreateILModule.fs @@ -136,17 +136,17 @@ let ValidateKeySigningAttributes (tcConfig: TcConfig, tcGlobals, topAttrs) = /// Get the object used to perform strong-name signing let GetStrongNameSigner signingInfo = let (StrongNameSigningInfo(delaysign, publicsign, signer, container)) = signingInfo - // REVIEW: favor the container over the key file - C# appears to do this match container with - | Some container -> Some(ILStrongNameSigner.OpenKeyContainer container) + | Some container -> + Some(ILStrongNameSigner.OpenKeyContainer (container, publicsign || delaysign)) | None -> match signer with | None -> None | Some bytes -> if publicsign || delaysign then - Some(ILStrongNameSigner.OpenPublicKeyOptions bytes publicsign) + Some(ILStrongNameSigner.OpenKeyPairFile(bytes, usePublicSign=true)) else - Some(ILStrongNameSigner.OpenKeyPairFile bytes) + Some(ILStrongNameSigner.OpenKeyPairFile(bytes, usePublicSign=false)) //---------------------------------------------------------------------------- // Building the contents of the finalized IL module