I need to use FIPS 140 compliant ECC cross platform. For a number of reasons, I can't use third-party libraries like BouncyCastle, so I am forced to use the underlying Crypto Service Provided on the Operating System. Obviously, I'll be using platform specific code for all of this.
I've got Windows, NetCore (for a Raspberry Pi), and Android (KNOX enabled Samsung device) working, but am having a hard time figuring out where/how to start for iOS.
The Android Device is a Samsung with KNOX and is using factory installed OpenSSL libraries. We've installed OpenSSL onto the Raspberry Pi and that is working as well. On Windows, the registry is set to use FIPS compliant algorithms and all is working. I
t's iOS I can't figure out!
note: None of this is designed for efficiency (yet), just focusing on getting it work first.
Some shared classes:
public class EcPrivateKey { public byte[] Value; public byte[] ValueX; public byte[] ValueY; public EcPrivateKey(byte[] value, byte[] valueX, byte[] valueY) { Value = value; ValueX = valueX; ValueY = valueY; } } public class EcPublicKey { public byte[] ValueX; public byte[] ValueY; public EcPublicKey() { } public EcPublicKey(byte[] x, byte[] y) { ValueX = x; ValueY = y; } }
For UWP and NetCore
public (EcPublicKey, EcPrivateKey) EcGenerateKeys() { using (var ec = ECDsa.Create(ECCurve.NamedCurves.nistP521)) { var keys = ec.ExportExplicitParameters(true); var ecPublicKey = new EcPublicKey(keys.Q.X, keys.Q.Y); var ecPrivateKey = new EcPrivateKey(keys.D, keys.Q.X, keys.Q.Y); return (ecPublicKey, ecPrivateKey); } } public byte[] EcSign(byte[] data, EcPrivateKey key) { var ecParameters = new ECParameters { D = key.Value, Q = new ECPoint { X = key.ValueX, Y = key.ValueY }, Curve = ECCurve.NamedCurves.nistP521 }; using (var ec = ECDsa.Create(ecParameters)) { return ec.SignData(data, HashAlgorithmName.SHA512); } } public bool EcVerify(byte[] data, byte[] signature, EcPublicKey key) { var point = new ECPoint { X = key.ValueX, Y = key.ValueY }; var ecParameters = new ECParameters { Q = point, Curve = ECCurve.NamedCurves.nistP521 }; using (var ec = ECDsa.Create(ecParameters)) { return ec.VerifyData(data, signature, HashAlgorithmName.SHA512); } }
For Android
public (EcPublicKey, EcPrivateKey) EcGenerateKeys() { var keyPairGenerator = KeyPairGenerator.GetInstance("EC"); keyPairGenerator.Initialize(new ECGenParameterSpec("secp521r1")); var keyPair = keyPairGenerator.GenerateKeyPair(); var keyFactory = KeyFactory.GetInstance("EC"); var publicSpec = Class.ForName("java.security.spec.ECPublicKeySpec"); var publicKeySpec = (ECPublicKeySpec)keyFactory.GetKeySpec(keyPair.Public, publicSpec); var w = publicKeySpec.GetW(); var wx = w.AffineX.ToByteArray(); var wy = w.AffineY.ToByteArray(); var ecPublicKey = new EcPublicKey(wx, wy); var privateSpec = Class.ForName("java.security.spec.ECPrivateKeySpec"); var privateKeySpec = (ECPrivateKeySpec)keyFactory.GetKeySpec(keyPair.Private, privateSpec); var s = privateKeySpec.GetS(); var ecPrivateKey = new EcPrivateKey(s.ToByteArray(), wx, wy); return (ecPublicKey, ecPrivateKey); } public byte[] EcSign(byte[] data, EcPrivateKey key) { var algorithmParameters = AlgorithmParameters.GetInstance("EC"); algorithmParameters.Init(new ECGenParameterSpec("secp521r1")); var algorithmSpec = Class.ForName("java.security.spec.ECParameterSpec"); var ecParameterSpec = (ECParameterSpec) algorithmParameters.GetParameterSpec(algorithmSpec); var ecPrivateKeySpec = new ECPrivateKeySpec(new BigInteger(key.Value), ecParameterSpec); var keyFactory = KeyFactory.GetInstance("EC"); var privateKey = keyFactory.GeneratePrivate(ecPrivateKeySpec); var ecSignature = Signature.GetInstance("SHA512withECDSA"); ecSignature.InitSign(privateKey); ecSignature.Update(data); return ecSignature.Sign(); } public bool EcVerify(byte[] data, byte[] signature, EcPublicKey key) { var algorithmParameters = AlgorithmParameters.GetInstance("EC"); algorithmParameters.Init(new ECGenParameterSpec("secp521r1")); var algorithmSpec = Class.ForName("java.security.spec.ECParameterSpec"); var ecParameterSpec = (ECParameterSpec) algorithmParameters.GetParameterSpec(algorithmSpec); var ecPublicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(key.ValueX), new BigInteger(key.ValueY)), ecParameterSpec); var keyFactory = KeyFactory.GetInstance("EC"); var publicKey = keyFactory.GeneratePublic(ecPublicKeySpec); var ecSignature = Signature.GetInstance("SHA512withECDSA"); ecSignature.InitVerify(publicKey); ecSignature.Update(data); return ecSignature.Verify(signature); }