/// <summary> /// Try to retrieve the public key from a crypto blob. /// </summary> /// <remarks> /// Can be either a PUBLICKEYBLOB or PRIVATEKEYBLOB. The BLOB must /// be unencrypted. /// </remarks> public unsafe static bool TryGetPublicKey(ImmutableArray <byte> blob, out ImmutableArray <byte> publicKey) { publicKey = ImmutableArray <byte> .Empty; // Is this already a strong name PublicKeyBlob? if (IsValidPublicKey(blob)) { publicKey = blob; return(true); } // Must be at least as large as header + RSA info if (blob.Length < sizeof(BlobHeader) + sizeof(RsaPubKey)) { return(false); } fixed(byte *backing = blob.DangerousGetUnderlyingArray()) { BlobHeader *header = (BlobHeader *)backing; RsaPubKey * rsa = (RsaPubKey *)(backing + sizeof(BlobHeader)); // The RSA magic key must match the blob id if (header->Type == PrivateKeyBlobId && rsa->Magic == RSA2) { return(TryGetPublicKeyFromPrivateKeyBlob(backing, blob.Length, out publicKey)); } else if (header->Type == PublicKeyBlobId && rsa->Magic == RSA1) { return(TryGetPublicKeyFromPublicKeyBlob(backing, blob.Length, out publicKey)); } } return(false); }
private unsafe static bool TryGetPublicKeyFromPrivateKeyBlob(byte *blob, int blobLen, out ImmutableArray <byte> publicKey) { BlobHeader *header = (BlobHeader *)blob; RsaPubKey * rsa = (RsaPubKey *)(blob + sizeof(BlobHeader)); byte version = header->Version; uint modulusBitLength = rsa->BitLen; uint exponent = rsa->PubExp; byte[] modulus = new byte[modulusBitLength >> 3]; if (blobLen - s_offsetToKeyData < modulus.Length) { publicKey = ImmutableArray <byte> .Empty; return(false); } Marshal.Copy((IntPtr)(blob + s_offsetToKeyData), modulus, 0, modulus.Length); BlobHeader newHeader = new BlobHeader() { Type = PublicKeyBlobId, Version = version, Reserved = 0, AlgId = AlgorithmId.RsaSign }; RsaPubKey newRsaKey = new RsaPubKey() { Magic = RSA1, // Public key BitLen = modulusBitLength, PubExp = exponent }; publicKey = CreateSnPublicKeyBlob(newHeader, newRsaKey, modulus); return(true); }