/// <summary> /// Initializes a new instance of the <see cref="RsaCryptographicKey" /> class. /// </summary> /// <param name="publicKey">The public key.</param> /// <param name="keyIdentifier">The key identifier that may be used to query the keychain.</param> /// <param name="algorithm">The algorithm.</param> internal RsaCryptographicKey(SecKey publicKey, string keyIdentifier, AsymmetricAlgorithm algorithm) { Requires.NotNull(publicKey, "publicKey"); this.publicKey = publicKey; this.keyIdentifier = keyIdentifier; this.algorithm = algorithm; }
/// <inheritdoc/> public ICryptographicKey ImportPublicKey(byte[] keyBlob, CryptographicPublicKeyBlobType blobType = CryptographicPublicKeyBlobType.X509SubjectPublicKeyInfo) { Requires.NotNull(keyBlob, "keyBlob"); RSAParameters parameters = KeyFormatter.GetFormatter(blobType).Read(keyBlob); // Inject the PKCS#1 public key into the KeyChain. string keyIdentifier = Guid.NewGuid().ToString(); string publicKeyIdentifier = RsaCryptographicKey.GetPublicKeyIdentifierWithTag(keyIdentifier); var keyQueryDictionary = RsaCryptographicKey.CreateKeyQueryDictionary(publicKeyIdentifier); keyQueryDictionary[KSec.ValueData] = NSData.FromArray(KeyFormatter.Pkcs1PrependZeros.Write(parameters, includePrivateKey: false)); keyQueryDictionary[KSec.AttrKeyClass] = KSec.AttrKeyClassPublic; keyQueryDictionary[KSec.ReturnRef] = NSNumber.FromBoolean(true); IntPtr resultHandle; int status = RsaCryptographicKey.SecItemAdd(keyQueryDictionary.Handle, out resultHandle); if (resultHandle != IntPtr.Zero) { var key = new SecKey(resultHandle, true); return new RsaCryptographicKey(key, keyIdentifier, this.Algorithm); } else { throw new InvalidOperationException("SecItemAdd return " + status); } }
/// <summary> /// Obtains a reference to an iOS security key given its identifying tag. /// </summary> /// <param name="tag">The tag of the key in the keychain.</param> /// <returns>The security key.</returns> private static SecKey KeyRefWithTag(string tag) { NSMutableDictionary queryKey = CreateKeyQueryDictionary(tag); queryKey[KSec.ReturnRef] = NSNumber.FromBoolean(true); IntPtr typeRef; int code = SecItemCopyMatching(queryKey.Handle, out typeRef); var keyRef = new SecKey(typeRef, owns: true); return keyRef; }
protected INativeObject GetINativeInstance(Type t) { var ctor = t.GetConstructor(Type.EmptyTypes); if ((ctor != null) && !ctor.IsAbstract) { return(ctor.Invoke(null) as INativeObject); } if (!NativeObjectInterfaceType.IsAssignableFrom(t)) { throw new ArgumentException("t"); } switch (t.Name) { case "CFAllocator": return(CFAllocator.SystemDefault); case "CFBundle": var bundles = CFBundle.GetAll(); if (bundles.Length > 0) { return(bundles [0]); } else { throw new InvalidOperationException(string.Format("Could not create the new instance for type {0}.", t.Name)); } case "CFNotificationCenter": return(CFNotificationCenter.Darwin); case "CFReadStream": case "CFStream": CFReadStream readStream; CFWriteStream writeStream; CFStream.CreatePairWithSocketToHost("www.google.com", 80, out readStream, out writeStream); return(readStream); case "CFWriteStream": CFStream.CreatePairWithSocketToHost("www.google.com", 80, out readStream, out writeStream); return(writeStream); case "CFUrl": return(CFUrl.FromFile("/etc")); case "AudioFile": var path = Path.GetFullPath("1.caf"); var af = AudioFile.Open(CFUrl.FromFile(path), AudioFilePermission.Read, AudioFileType.CAF); return(af); case "CFHTTPMessage": return(CFHTTPMessage.CreateEmpty(false)); case "CGBitmapContext": byte[] data = new byte [400]; using (CGColorSpace space = CGColorSpace.CreateDeviceRGB()) { return(new CGBitmapContext(data, 10, 10, 8, 40, space, CGBitmapFlags.PremultipliedLast)); } case "CGContextPDF": var filename = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + "/t.pdf"; using (var url = new NSUrl(filename)) return(new CGContextPDF(url)); case "CGColorConverter": var cvt = new CGColorConverterTriple() { Space = CGColorSpace.CreateGenericRgb(), Intent = CGColorRenderingIntent.Default, Transform = CGColorConverterTransformType.ApplySpace }; return(new CGColorConverter(null, cvt, cvt, cvt)); case "CGDataConsumer": using (NSMutableData destData = new NSMutableData()) { return(new CGDataConsumer(destData)); } case "CGDataProvider": filename = "xamarin1.png"; return(new CGDataProvider(filename)); case "CGFont": return(CGFont.CreateWithFontName("Courier New")); case "CGPattern": return(new CGPattern( new RectangleF(0, 0, 16, 16), CGAffineTransform.MakeIdentity(), 16, 16, CGPatternTiling.NoDistortion, true, (cgc) => {})); case "CMBufferQueue": return(CMBufferQueue.CreateUnsorted(2)); case "CTFont": CTFontDescriptorAttributes fda = new CTFontDescriptorAttributes() { FamilyName = "Courier", StyleName = "Bold", Size = 16.0f }; using (var fd = new CTFontDescriptor(fda)) return(new CTFont(fd, 10, CTFontOptions.Default)); case "CTFontCollection": return(new CTFontCollection(new CTFontCollectionOptions())); case "CTFontDescriptor": fda = new CTFontDescriptorAttributes(); return(new CTFontDescriptor(fda)); case "CTTextTab": return(new CTTextTab(CTTextAlignment.Left, 2)); case "CTTypesetter": return(new CTTypesetter(new NSAttributedString("Hello, world", new CTStringAttributes() { ForegroundColorFromContext = true, Font = new CTFont("Arial", 24) }))); case "CTFrame": var framesetter = new CTFramesetter(new NSAttributedString("Hello, world", new CTStringAttributes() { ForegroundColorFromContext = true, Font = new CTFont("Arial", 24) })); var bPath = UIBezierPath.FromRect(new RectangleF(0, 0, 3, 3)); return(framesetter.GetFrame(new NSRange(0, 0), bPath.CGPath, null)); case "CTFramesetter": return(new CTFramesetter(new NSAttributedString("Hello, world", new CTStringAttributes() { ForegroundColorFromContext = true, Font = new CTFont("Arial", 24) }))); case "CTGlyphInfo": return(new CTGlyphInfo("Zapfino", new CTFont("Arial", 24), "Foo")); case "CTLine": return(new CTLine(new NSAttributedString("Hello, world", new CTStringAttributes() { ForegroundColorFromContext = true, Font = new CTFont("Arial", 24) }))); case "CGImageDestination": var storage = new NSMutableData(); return(CGImageDestination.Create(new CGDataConsumer(storage), "public.png", 1)); case "CGImageMetadataTag": using (NSString name = new NSString("tagName")) using (var value = new NSString("value")) return(new CGImageMetadataTag(CGImageMetadataTagNamespaces.Exif, CGImageMetadataTagPrefixes.Exif, name, CGImageMetadataType.Default, value)); case "CGImageSource": filename = "xamarin1.png"; return(CGImageSource.FromUrl(NSUrl.FromFilename(filename))); case "SecPolicy": return(SecPolicy.CreateSslPolicy(false, null)); case "SecIdentity": using (var options = NSDictionary.FromObjectAndKey(new NSString("farscape"), SecImportExport.Passphrase)) { NSDictionary[] array; var result = SecImportExport.ImportPkcs12(farscape_pfx, options, out array); if (result != SecStatusCode.Success) { throw new InvalidOperationException(string.Format("Could not create the new instance for type {0} due to {1}.", t.Name, result)); } return(new SecIdentity(array [0].LowlevelObjectForKey(SecImportExport.Identity.Handle))); } case "SecTrust": X509Certificate x = new X509Certificate(mail_google_com); using (var policy = SecPolicy.CreateSslPolicy(true, "mail.google.com")) return(new SecTrust(x, policy)); case "SslContext": return(new SslContext(SslProtocolSide.Client, SslConnectionType.Stream)); case "UIFontFeature": return(new UIFontFeature(CTFontFeatureNumberSpacing.Selector.ProportionalNumbers)); case "NetworkReachability": return(new NetworkReachability(IPAddress.Loopback, null)); #if !__TVOS__ case "VTCompressionSession": case "VTSession": return(VTCompressionSession.Create(1024, 768, CMVideoCodecType.H264, (sourceFrame, status, flags, buffer) => { }, null, (CVPixelBufferAttributes)null)); case "VTFrameSilo": return(VTFrameSilo.Create()); case "VTMultiPassStorage": return(VTMultiPassStorage.Create()); #endif case "CFString": return(new CFString("test")); case "DispatchQueue": return(new DispatchQueue("com.example.subsystem.taskXYZ")); case "DispatchGroup": return(DispatchGroup.Create()); case "CGColorSpace": return(CGColorSpace.CreateAcesCGLinear()); case "CGGradient": CGColor[] cArray = { UIColor.Black.CGColor, UIColor.Clear.CGColor, UIColor.Blue.CGColor }; return(new CGGradient(null, cArray)); case "CGImage": filename = "xamarin1.png"; using (var dp = new CGDataProvider(filename)) return(CGImage.FromPNG(dp, null, false, CGColorRenderingIntent.Default)); case "CGColor": return(UIColor.Black.CGColor); case "CMClock": CMClockError ce; CMClock clock = CMClock.CreateAudioClock(out ce); if (ce == CMClockError.None) { return(clock); } throw new InvalidOperationException(string.Format("Could not create the new instance for type {0}.", t.Name)); case "CMTimebase": clock = CMClock.CreateAudioClock(out ce); if (ce == CMClockError.None) { return(new CMTimebase(clock)); } throw new InvalidOperationException(string.Format("Could not create the new instance for type {0}.", t.Name)); case "CVPixelBufferPool": return(new CVPixelBufferPool( new CVPixelBufferPoolSettings(), new CVPixelBufferAttributes(CVPixelFormatType.CV24RGB, 100, 50) )); case "SecCertificate": using (var cdata = NSData.FromArray(mail_google_com)) return(new SecCertificate(cdata)); case "SecKey": SecKey private_key; SecKey public_key; using (var record = new SecRecord(SecKind.Key)) { record.KeyType = SecKeyType.RSA; record.KeySizeInBits = 512; // it's not a performance test :) SecKey.GenerateKeyPair(record.ToDictionary(), out public_key, out private_key); return(private_key); } case "SecAccessControl": return(new SecAccessControl(SecAccessible.WhenPasscodeSetThisDeviceOnly)); default: throw new InvalidOperationException(string.Format("Could not create the new instance for type {0}.", t.Name)); } }
public void RoundtripRSA512PKCS1() { NSError error; SecKey private_key; SecKey public_key; using (var record = new SecRecord(SecKind.Key)) { record.KeyType = SecKeyType.RSA; record.KeySizeInBits = 512; // it's not a performance test :) Assert.That(SecKey.GenerateKeyPair(record.ToDictionary(), out public_key, out private_key), Is.EqualTo(SecStatusCode.Success), "GenerateKeyPair"); byte [] plain = new byte [20] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; byte [] cipher; if (TestRuntime.CheckXcodeVersion(8, 0)) { Assert.True(public_key.IsAlgorithmSupported(SecKeyOperationType.Encrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "public/IsAlgorithmSupported/Encrypt"); // I would have expect false Assert.True(public_key.IsAlgorithmSupported(SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "public/IsAlgorithmSupported/Decrypt"); using (var pub = public_key.GetPublicKey()) { // a new native instance of the key is returned (so having a new managed SecKey is fine) Assert.That(pub.Handle, Is.Not.EqualTo(public_key.Handle), "public/GetPublicKey"); } using (var attrs = public_key.GetAttributes()) { Assert.That(attrs.Count, Is.GreaterThan(0), "public/GetAttributes"); } using (var data = public_key.GetExternalRepresentation(out error)) { Assert.Null(error, "public/error-1"); Assert.NotNull(data, "public/GetExternalRepresentation"); using (var key = SecKey.Create(data, SecKeyType.RSA, SecKeyClass.Public, 512, null, out error)) { Assert.Null(error, "public/Create/error-1"); } } } Assert.That(public_key.Encrypt(SecPadding.PKCS1, plain, out cipher), Is.EqualTo(SecStatusCode.Success), "Encrypt"); byte[] result; if (TestRuntime.CheckXcodeVersion(8, 0)) { Assert.False(private_key.IsAlgorithmSupported(SecKeyOperationType.Encrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "private/IsAlgorithmSupported/Encrypt"); Assert.True(private_key.IsAlgorithmSupported(SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "private/IsAlgorithmSupported/Decrypt"); using (var pub2 = private_key.GetPublicKey()) { // a new native instance of the key is returned (so having a new managed SecKey is fine) Assert.That(pub2.Handle, Is.Not.EqualTo(public_key.Handle), "private/GetPublicKey"); } using (var attrs = private_key.GetAttributes()) { Assert.That(attrs.Count, Is.GreaterThan(0), "private/GetAttributes"); } using (var data2 = private_key.GetExternalRepresentation(out error)) { Assert.Null(error, "private/error-1"); Assert.NotNull(data2, "private/GetExternalRepresentation"); using (var key = SecKey.Create(data2, SecKeyType.RSA, SecKeyClass.Private, 512, null, out error)) { Assert.Null(error, "private/Create/error-1"); } } } public_key.Dispose(); Assert.That(private_key.Decrypt(SecPadding.PKCS1, cipher, out result), Is.EqualTo(SecStatusCode.Success), "Decrypt"); Assert.That(plain, Is.EqualTo(result), "match"); private_key.Dispose(); } }
public void RoundtripRSAMinPKCS1() { NSError error; SecKey private_key; SecKey public_key; using (var record = new SecRecord(SecKind.Key)) { record.KeyType = SecKeyType.RSA; record.KeySizeInBits = MinRsaKeySize; // it's not a performance test :) Assert.That(SecKey.GenerateKeyPair(record.ToDictionary(), out public_key, out private_key), Is.EqualTo(SecStatusCode.Success), "GenerateKeyPair"); byte [] plain = new byte [20] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; byte [] cipher; if (TestRuntime.CheckXcodeVersion(8, 0)) { Assert.True(public_key.IsAlgorithmSupported(SecKeyOperationType.Encrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "public/IsAlgorithmSupported/Encrypt"); #if MONOMAC Assert.That(public_key.IsAlgorithmSupported(SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), Is.EqualTo(TestRuntime.CheckSystemVersion(PlatformName.MacOSX, 10, 13)), "public/IsAlgorithmSupported/Decrypt"); using (var pub = public_key.GetPublicKey()) { // macOS behaviour is not consistent - but the test main goal is to check we get a key Assert.That(pub.Handle, Is.Not.EqualTo(IntPtr.Zero), "public/GetPublicKey"); } #else Assert.True(public_key.IsAlgorithmSupported(SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "public/IsAlgorithmSupported/Decrypt"); using (var pub = public_key.GetPublicKey()) { // a new native instance of the key is returned (so having a new managed SecKey is fine) Assert.False(pub.Handle == public_key.Handle, "public/GetPublicKey"); } #endif using (var attrs = public_key.GetAttributes()) { Assert.That(attrs.Count, Is.GreaterThan(0), "public/GetAttributes"); } using (var data = public_key.GetExternalRepresentation(out error)) { Assert.Null(error, "public/error-1"); Assert.NotNull(data, "public/GetExternalRepresentation"); using (var key = SecKey.Create(data, SecKeyType.RSA, SecKeyClass.Public, MinRsaKeySize, null, out error)) { Assert.Null(error, "public/Create/error-1"); } } } Assert.That(public_key.Encrypt(SecPadding.PKCS1, plain, out cipher), Is.EqualTo(SecStatusCode.Success), "Encrypt"); byte[] result; if (TestRuntime.CheckXcodeVersion(8, 0)) { Assert.False(private_key.IsAlgorithmSupported(SecKeyOperationType.Encrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "private/IsAlgorithmSupported/Encrypt"); Assert.True(private_key.IsAlgorithmSupported(SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "private/IsAlgorithmSupported/Decrypt"); #if MONOMAC using (var pub2 = private_key.GetPublicKey()) { Assert.That(pub2.Handle, Is.EqualTo(public_key.Handle), "private/GetPublicKey"); } #else using (var pub2 = private_key.GetPublicKey()) { // a new native instance of the key is returned (so having a new managed SecKey is fine) Assert.That(pub2.Handle, Is.Not.EqualTo(public_key.Handle), "private/GetPublicKey"); } #endif using (var attrs = private_key.GetAttributes()) { Assert.That(attrs.Count, Is.GreaterThan(0), "private/GetAttributes"); } using (var data2 = private_key.GetExternalRepresentation(out error)) { Assert.Null(error, "private/error-1"); Assert.NotNull(data2, "private/GetExternalRepresentation"); using (var key = SecKey.Create(data2, SecKeyType.RSA, SecKeyClass.Private, MinRsaKeySize, null, out error)) { Assert.Null(error, "private/Create/error-1"); } } } public_key.Dispose(); var expectedResult = SecStatusCode.Success; #if __MACOS__ if (!TestRuntime.CheckSystemVersion(PlatformName.MacOSX, 10, 8)) { expectedResult = SecStatusCode.InvalidData; } #endif Assert.That(private_key.Decrypt(SecPadding.PKCS1, cipher, out result), Is.EqualTo(expectedResult), "Decrypt"); if (expectedResult != SecStatusCode.InvalidData) { Assert.That(plain, Is.EqualTo(result), "match"); } private_key.Dispose(); } }