Skip to content

Instantly share code, notes, and snippets.

@richlander
Created April 5, 2017 04:07

Revisions

  1. richlander created this gist Apr 5, 2017.
    89 changes: 89 additions & 0 deletions dotnet47-crypto-improvements.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,89 @@
    privatestaticECDsa CreatePublicKey(ECDsa privateKey)
    {
    // Export the public portion of the ECDSA key.
    // The public portion being the curve and the Q point.
    ECParameters keyParameters = privateKey.ExportParameters(includePrivateParameters:false);

    // Rather than having to create a key and call ImportParameters you can just pass the
    // parameters to Create for a convenient one-liner.
    returnECDsa.Create(keyParameters);
    }

    privatestaticECDsa CreateBrainpoolKeyIfAble()
    {
    try
    {
    // New with Windows 10; will throw on earlier Windows versions
    returnECDsa.Create(ECCurve.NamedCurves.brainpoolP256r1);
    }
    catch (PlatformNotSupportedException)
    {
    returnnull;
    }
    }

    privatestaticECCurve? s_explicitNistP256Curve;
    privatestaticECDsa NormalizeToNamedCurve(ECDsa ecdsa)
    {
    ECParameters publicParameters = ecdsa.ExportParameters(false);
    ECCurve keyCurve = publicParameters.Curve;

    if (keyCurve.IsNamed)
    {
    return ecdsa;
    }

    if (!keyCurve.IsExplicit)
    {
    // Currently the only option which is neither Named or Explicit is Implicit,
    // which should never come back from Export. But, who knows what the future holds?
    thrownewInvalidOperationException();
    }

    ECCurve nistp256;

    if (!s_explicitNistP256Curve.HasValue)
    {
    // Create a key using the NIST P-256 curve.
    using (ECDsa temp = ECDsa.Create(ECCurve.NamedCurves.nistP256))
    {
    // Export the parameters with explicit curve form, giving
    // G, P, and the rest.
    nistp256 = temp.ExportExplicitParameters(false).Curve;
    }

    s_explicitNistP256Curve = nistp256;
    }
    else
    {
    nistp256 = s_explicitNistP256Curve.Value;
    }

    if (keyCurve.IsPrime == nistp256.IsPrime &&
    keyCurve.A.SequenceEqual(nistp256.A) &&
    keyCurve.B.SequenceEqual(nistp256.B) &&
    keyCurve.Prime.SequenceEqual(nistp256.Prime) &&
    keyCurve.G.X.SequenceEqual(nistp256.G.X) &&
    keyCurve.G.Y.SequenceEqual(nistp256.G.Y))
    {
    // Order and Cofactor could also be checked, but they're derived terms.
    // Hash and Seed could also be checked, but they're not guaranteed to
    // be exported.

    ECParameters reimportParameters =newECParameters
    {
    Curve =ECCurve.NamedCurves.nistP256,
    Q = publicParameters.Q,
    };

    // This example just uses the public key, but if you wanted to normalize
    // a private key you could try exporting with private parameters, but
    // beware of exceptions (no private key, key not exportable)
    ECDsa newobj =ECDsa.Create(reimportParameters);
    ecdsa.Dispose();
    return newobj;
    }

    // Not sure what this is, but it isn't nistp256!
    returnnull;
    }