public byte[] ToDER(bool compressed) { AssertPrivateKey(); MemoryStream baos = new MemoryStream(); // ASN1_SEQUENCE(EC_PRIVATEKEY) = { // ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), // ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), // ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), // ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) // } ASN1_SEQUENCE_END(EC_PRIVATEKEY) DerSequenceGenerator seq = new DerSequenceGenerator(baos); seq.AddObject(new DerInteger(1)); // version seq.AddObject(new DerOctetString(PrivateKey.D.ToByteArrayUnsigned())); //Did not managed to generate the same der as brainwallet by using this //seq.AddObject(new DerTaggedObject(0, Secp256k1.ToAsn1Object())); Asn1Object secp256k1Der = null; if (compressed) { secp256k1Der = DerSequence.FromByteArray(DataEncoders.Encoders.Hex.DecodeData("308182020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101")); } else { secp256k1Der = DerSequence.FromByteArray(DataEncoders.Encoders.Hex.DecodeData("3081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101")); } seq.AddObject(new DerTaggedObject(0, secp256k1Der)); seq.AddObject(new DerTaggedObject(1, new DerBitString(GetPubKey(compressed).ToBytes()))); seq.Close(); return(baos.ToArray()); }
/// <summary> /// Parses and checks contents of the DICE extension /// </summary> /// <param name="c">Certificate to validate</param> /// <returns>Extension is well formed</returns> bool CheckDICEExtension(X509Certificate c) { var criticalOids = c.GetCriticalExtensionOids(); if (criticalOids.Contains(DICEExtensionOid)) { Error("DICE extension is marked critical and should be non-critical"); return(false); } var nonCriticalOids = c.GetNonCriticalExtensionOids(); if (!nonCriticalOids.Contains(DICEExtensionOid)) { Error("DICE extension not found"); return(false); } var diceExtension = c.GetExtensionValue(new DerObjectIdentifier(DICEExtensionOid)); try { DerOctetString envelope = (DerOctetString)DerOctetString.FromByteArray(diceExtension.GetEncoded()); DerSequence seq = (DerSequence)DerSequence.FromByteArray(envelope.GetOctets()); // first field is version number var versionNumber = (DerInteger)seq[0]; if (versionNumber.PositiveValue.IntValue != 1) { Error($"DICE Extension has Wrong version number. Expecing {DICEExtensionVersionNumber}, cert contains {versionNumber.ToString()}"); return(false); } // second field is DeviceID var devIdPubKey = SubjectPublicKeyInfo.GetInstance(seq[1]); // will check it's good later PubKeyInfoFromDICEExtension = devIdPubKey; // third field contains {hashOid, hashVal} var hashEnvelope = (DerSequence)seq[2]; var hashAlg = (DerObjectIdentifier)hashEnvelope[0]; if (hashAlg.Id != NistObjectIdentifiers.IdSha256.ToString()) { Error("DICE Extension hash alg is wrong. "); return(false); } var hashVal = (DerOctetString)hashEnvelope[1]; if (hashVal.GetOctets().Length != 32) { Error("DICE Extension hash value length is wrong. "); return(false); } } catch (Exception e) { Error($"Failed to parse the DICE extension. Parsing exception was {e.ToString()}"); return(false); } return(true); }
/// <summary> /// Parses the AddedTo data that is returned from TPM2_CertifyX509() /// </summary> /// <param name="data"></param> /// <returns></returns> public static AddedToCertificate FromDerEncoding(byte[] data) { var ret = new AddedToCertificate(); var sequence = (DerSequence)DerSequence.FromByteArray(data); var taggedVersion = (DerTaggedObject)(sequence[0]); Debug.Assert(taggedVersion.TagNo == 0); ret.Version = (DerInteger)taggedVersion.GetObject(); ret.SerialNumber = (DerInteger)sequence[1]; ret.Signature = AlgorithmIdentifier.GetInstance(sequence[2]); ret.SubjectPublicKeyInfo = SubjectPublicKeyInfo.GetInstance(sequence[3]); return(ret); }
/// <summary> /// If a device presents a "bare" certificate rather than a full certificate chain, we have to /// peform some steps that would normall be performed by the X509 chain builder. Specifically, /// the RIoT extension (above) encodes the DeviceID public key, but we have to check that this /// Alias Cert was actually signed by the corresponding DeviceID private key. To do this we /// parse the Alias Cert to get: /// The "to be signed" region (byte array) /// The OID of the signature scheme /// The signature block /// /// The caller of this function can then check that the ALias Cert was indeed signed by the /// device it claims to be from. /// </summary> /// <param name="aliasCert"></param> /// <returns></returns> static internal DecomposedCert Decompose(X509Certificate2 aliasCert) { var rawData = aliasCert.GetRawCertData(); try { DerSequence seq = (DerSequence)DerSequence.FromByteArray(rawData); DerSequence tbs = (DerSequence)seq[0]; DerSequence sigAlg = (DerSequence)seq[1]; var sigAlgOid = (DerObjectIdentifier)sigAlg[0]; DerBitString sigData = (DerBitString)seq[2]; DerSequence sigSequence = (DerSequence)DerSequence.FromByteArray(sigData.GetOctets()); var sig1 = (DerInteger)sigSequence[0]; var sig2 = (DerInteger)sigSequence[0]; var sig1Bytes = sig1.Value.ToByteArrayUnsigned(); var sig2Bytes = sig1.Value.ToByteArrayUnsigned(); Debug.Assert(sig1Bytes.Length == 32 && sig1Bytes.Length == 32); byte[] SignatureX = new byte[64]; Array.Copy(sig1Bytes, 0, SignatureX, 0, 32); Array.Copy(sig2Bytes, 0, SignatureX, 32, 32); Debug.WriteLine(""); DecomposedCert bits = new DecomposedCert { Tbs = tbs.GetDerEncoded(), OID = sigAlgOid.Id, Signature = SignatureX }; return(bits); } catch (Exception e) { Debug.WriteLine(e.ToString()); return(null); } }
static internal RIoTDeviceInfo Decode(X509Certificate2 aliasCert) { AsnEncodedData altNames = null; foreach (var ext in aliasCert.Extensions) { if (ext.Oid.Value != RIoTOid) { continue; } altNames = new AsnEncodedData(ext.Oid, ext.RawData); } // an AltName is mandatory if (altNames == null) { Helpers.Notify("Certificate does not have an altName field", true); return(null); } // parse the extension: this is a collection of nested thus - /* * DER Sequence * ObjectIdentifier(1.2.3.4.5.6) <- RIoT Composite ID OID * DER Sequence * Integer(1) <- Version number * DER Sequence <- DeviceID public key * DER Sequence (same encoding as in DeviceID cert) * ObjectIdentifier(1.2.840.10045.2.1) EC pubkey * ObjectIdentifier(1.2.840.10045.3.1.7) prime256 * DER Bit String[65, 0] key value * DER Sequence <- Encoded FWID * ObjectIdentifier(2.16.840.1.101.3.4.2.1) sha256 * DER Octet String[32] FWID hash value * * * */ try { DerSequence seq = (DerSequence)DerSequence.FromByteArray(altNames.RawData); //DerTaggedObject obj = (DerTaggedObject)seq[0]; //DerSequence obj2 = (DerSequence)obj.GetObject(); //var oid = (DerObjectIdentifier)obj2[0]; //if (oid.Id != RIoTOid) return ParseError("Incorrect RIoT OID"); var versionNumber = (DerInteger)seq[0]; if (versionNumber.PositiveValue.IntValue != 1) { return(ParseError("Wrong version number")); } DerSequence obj4 = (DerSequence)seq[1]; DerSequence obj5 = (DerSequence)obj4[0]; var keyAlg1 = (DerObjectIdentifier)obj5[0]; var keyAlg2 = (DerObjectIdentifier)obj5[1]; if (keyAlg1.Id != ecPubKeyOID) { return(ParseError("Bad ECPubKey OID")); } if (keyAlg2.Id != prime256v1Oid) { return(ParseError("Bad curve OID")); } var key = (DerBitString)obj4[1]; var obj4b = (DerSequence)seq[2]; var hashAlg = (DerObjectIdentifier)obj4b[0]; if (hashAlg.Id != sha256Oid) { return(ParseError("Bad fwid hash OID")); } var hash = (DerOctetString)obj4b[1]; RIoTDeviceInfo deviceInfo = new RIoTDeviceInfo() { FirmwareID = hash.GetOctets(), EncodedDeviceIDKey = key.GetBytes(), Cert = aliasCert }; return(deviceInfo); } catch (Exception e) { Debug.WriteLine(e.ToString()); return(null); } }
SimulateX509Certify(PartialCertificate partialCert, AsymmetricKeyParameter publicKeyToCertify, AsymmetricKeyParameter signingKey, string signingAlgorithm) { // We can simulate ECDSA/SHA256 and RSA/SHA256 ISignatureFactory signatureFactory; DerObjectIdentifier sigAlgOid; if (signingKey is ECPrivateKeyParameters) { sigAlgOid = X9ObjectIdentifiers.ECDsaWithSha256; } else { sigAlgOid = PkcsObjectIdentifiers.Sha256WithRsaEncryption; } //signatureFactory = new Asn1SignatureFactory(sigAlgOid.ToString(), signingKey); signatureFactory = new Asn1SignatureFactory(sigAlgOid.ToString(), signingKey); // Make the certificate var certGenerator = new X509V3CertificateGenerator(); certGenerator.SetIssuerDN(partialCert.Issuer); certGenerator.SetSubjectDN(partialCert.Subject); certGenerator.SetSerialNumber(BigInteger.ValueOf(1)); certGenerator.SetNotBefore(partialCert.NotBefore); certGenerator.SetNotAfter(partialCert.NotAfter); certGenerator.SetPublicKey(publicKeyToCertify); if (partialCert.SubjectUniqueId != null) { certGenerator.SetSubjectUniqueID(ByteArrayToBoolArray(partialCert.SubjectUniqueId)); } if (partialCert.IssuerUniqueId != null) { certGenerator.SetIssuerUniqueID(ByteArrayToBoolArray(partialCert.IssuerUniqueId)); } // process the extensions. Note that this will not preserve the order var extensions = partialCert.Extensions; if (extensions != null) { foreach (var critExtOid in extensions.GetCriticalExtensionOids()) { certGenerator.AddExtension(critExtOid.ToString(), true, extensions.GetExtension(critExtOid).GetParsedValue()); } foreach (var nonCritExtOid in extensions.GetNonCriticalExtensionOids()) { certGenerator.AddExtension(nonCritExtOid.ToString(), false, extensions.GetExtension(nonCritExtOid).GetParsedValue()); } } // and sign to make the cert var cert = certGenerator.Generate(signatureFactory); // take things apart again for addedToCert var subjectPubKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKeyToCertify); // get the exact bytes for the signature algorithm var tbsSequence = ((DerSequence)DerSequence.FromByteArray(cert.GetTbsCertificate())); var sigAlgBytes = tbsSequence[2]; AddedToCertificate addedTo = new AddedToCertificate() { Version = new DerInteger(BigInteger.ValueOf(cert.Version)), SerialNumber = new DerInteger(cert.SerialNumber), Signature = AlgorithmIdentifier.GetInstance(sigAlgBytes), SubjectPublicKeyInfo = subjectPubKeyInfo }; return(System.ValueTuple.Create(cert, addedTo)); }
public static CngKey Import(Byte[] blob, Int32 offset = 0) { Boolean isPrivateKey = false; Byte keyLength = 0; Byte[] keyCurveX = null, keyCurveY = null, keyScalar = null; Byte[] inBlob = blob; // Apply offset to incoming data. if (offset > 0) { var blobLength = blob.Length - (offset); inBlob = new Byte[blobLength]; Array.Copy(blob, offset, inBlob, 0, blobLength); } System.IO.File.WriteAllBytes("Key.key", inBlob); DerSequence der = (DerSequence)DerSequence.FromByteArray(inBlob); try { /*to read directly*/ isPrivateKey = ((DerBitString)der[0]).IntValue != 0; } catch { der = (DerSequence)DerSequence.FromByteArray(((DerOctetString)der[1]).GetOctets()); System.IO.File.WriteAllBytes("KeyDer.key", der.GetEncoded()); } // Read Data from Key. isPrivateKey = ((DerBitString)der[0]).IntValue != 0; keyLength = (Byte)((DerInteger)der[1]).PositiveValue.IntValue; keyCurveX = ((DerInteger)der[2]).PositiveValue.ToByteArrayUnsigned(); keyCurveY = ((DerInteger)der[3]).PositiveValue.ToByteArrayUnsigned(); if (isPrivateKey) { keyScalar = ((DerInteger)der[4]).PositiveValue.ToByteArrayUnsigned(); } // Validate data. if (keyLength == 0) { throw new IndexOutOfRangeException("Length of key is 0."); } if (keyCurveX == null || keyCurveY == null) { throw new IndexOutOfRangeException("Key Curve is not set."); } // Construct a readable key out of this data. Byte[] newBlob = new Byte[8 + (keyLength * (2 + (isPrivateKey ? 1 : 0)))]; // Write Key Header for ECCPrivateBlob or ECCPublicBlob. newBlob[0] = (Byte)0x45; // E newBlob[1] = (Byte)0x43; // C newBlob[2] = (Byte)0x4B; // K newBlob[3] = (Byte)(keyLength == 32 ? 0x31 : (keyLength == 48 ? 0x33 : (keyLength == 64 ? 0x35 : 0x00))); newBlob[3] += (Byte)(isPrivateKey ? 0x01 : 0x00); newBlob[4] = (Byte)keyLength; Array.Copy(keyCurveX, 0, newBlob, 8, keyCurveX.Length); Array.Copy(keyCurveY, 0, newBlob, 8 + keyLength, keyCurveY.Length); if (isPrivateKey) { Array.Copy(keyScalar, 0, newBlob, 8 + keyLength * 2, keyScalar.Length); } // Now return a valid Key. if (isPrivateKey) { return(CngKey.Import(newBlob, CngKeyBlobFormat.EccPrivateBlob)); } else { return(CngKey.Import(newBlob, CngKeyBlobFormat.EccPublicBlob)); } }