public SignatureSubPacket[] ParsePackets(byte[] bBinaryData) { ArrayList alPackets = new ArrayList(100); byte[] bTmpData = new byte[bBinaryData.Length]; Array.Copy(bBinaryData, bTmpData, bBinaryData.Length); long iCurrentIndex = 0; while (iCurrentIndex < bBinaryData.Length) { SignatureSubPacket pTmpPacket = new SignatureSubPacket(); SignatureSubPacket pCurrentPacket = pTmpPacket.ParsePacket(bTmpData); iCurrentIndex += pCurrentPacket.Length; alPackets.Add(pCurrentPacket); bTmpData = new byte[bTmpData.Length - pCurrentPacket.Length]; Array.Copy(bBinaryData, (int)iCurrentIndex, bTmpData, 0, bBinaryData.Length - (int)iCurrentIndex); } SignatureSubPacket[] pReturnPackets = new SignatureSubPacket[alPackets.Count]; IEnumerator iePacketEnum = alPackets.GetEnumerator(); int iCount = 0; while (iePacketEnum.MoveNext()) { pReturnPackets[iCount++] = (SignatureSubPacket)iePacketEnum.Current; } return(pReturnPackets); }
public static string ClearTextSign(string strMessage, SecretKeyRing skrKeyRing) { SignaturePacket spSign = new SignaturePacket(); strMessage = Radix64.TrimMessage(strMessage); QueryPassphrase qpPassphrase = new QueryPassphrase(); qpPassphrase.ShowMyDialog(skrKeyRing); string strPassphrase = qpPassphrase.Passphrase; TransportableSecretKey tskKey = qpPassphrase.SelectedKey; SecretKeyPacket skpKey = tskKey.FindKey(AsymActions.Sign); Working wWorking = new Working(); wWorking.Show(); spSign.HashAlgorithm = HashAlgorithms.SHA1; spSign.Format = PacketFormats.New; wWorking.Progress(10); SignatureSubPacket sspCreator = new SignatureSubPacket(); sspCreator.Type = SignatureSubPacketTypes.IssuerKeyID; sspCreator.KeyID = skpKey.PublicKey.KeyID; SignatureSubPacket sspCreationTime = new SignatureSubPacket(); sspCreationTime.Type = SignatureSubPacketTypes.SignatureCreationTime; sspCreationTime.TimeCreated = DateTime.Now; spSign.HashedSubPackets = new SignatureSubPacket[2]; spSign.HashedSubPackets[0] = sspCreator; spSign.HashedSubPackets[1] = sspCreationTime; wWorking.Progress(20); //spSign.KeyID = skpKey.PublicKey.KeyID; //spSign.TimeCreated = DateTime.Now; spSign.SignatureAlgorithm = skpKey.PublicKey.Algorithm; spSign.SignatureType = SignatureTypes.TextSignature; spSign.Version = SignaturePacketVersionNumbers.v4; wWorking.Progress(10); byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(strMessage); spSign.Sign(bMessage, skpKey, strPassphrase); wWorking.Progress(40); byte[] bSignature = spSign.Generate(); string strSignature = Radix64.Encode(bSignature, true); wWorking.Progress(20); string strFinal = Armor.WrapCleartextSignature(strMessage, strSignature); wWorking.Hide(); return strFinal; }
/// <summary> /// Creates a new signature packet. Format defaults /// to new packet format. /// </summary> /// <remarks>No remarks</remarks> public SignaturePacket() { bBody = new byte[0]; bHeader = new byte[0]; pfFormat = PacketFormats.New; ctContent = ContentTypes.Signature; dtTimeCreated = DateTime.Now; HashedSubPackets = new SignatureSubPacket[0]; UnhashedSubPackets = new SignatureSubPacket[0]; this.bIsUpdated = true; }
public void AddSubPacket(SignatureSubPacket sspSubPacket, bool bHashed) { if (bHashed) { SignatureSubPacket[] sspHashed = new SignatureSubPacket[this.HashedSubPackets.Length + 1]; Array.Copy(this.HashedSubPackets, 0, sspHashed, 0, this.HashedSubPackets.Length); sspHashed[sspHashed.Length - 1] = sspSubPacket; this.HashedSubPackets = sspHashed; } else { SignatureSubPacket[] sspUnhashed = new SignatureSubPacket[this.UnhashedSubPackets.Length + 1]; Array.Copy(this.HashedSubPackets, 0, sspUnhashed, 0, this.UnhashedSubPackets.Length); sspUnhashed[sspUnhashed.Length - 1] = sspSubPacket; this.UnhashedSubPackets = sspUnhashed; } this.bIsUpdated = true; }
/// <summary> /// Adds a userID to the specified key /// </summary> /// <param name="userID">user id to be added</param> /// <param name="email">user email address</param> /// <param name="infos">xml encoded user infos</param> /// <param name="strPassphrase">passphrase of the secret key we want to add the user id to</param> /// <param name="KeyID">keyID of the key we want to add the userID to</param> /// <param name="isRevocable">is a revocable keyID</param> public void AddUserID(string userID, string email, string infos, string strPassphrase, ulong KeyID, bool isRevocable) { TransportablePublicKey tpkKey = this.PublicRing.Find(KeyID,false); TransportableSecretKey tskKey = this.SecretRing.Find(KeyID); if (tpkKey != null && tskKey != null) { CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = userID.Trim() + " <" + email.Trim() + ">"; cuiUID.UserID = uipUID; SecretKeyPacket skpSignatureKey = tskKey.FindKey(AsymActions.Sign); SignaturePacket spSelfSig = new SignaturePacket(); if (infos != null) { SignatureSubPacket sspNotation = new SignatureSubPacket(); sspNotation.Type = SignatureSubPacketTypes.NotationData; sspNotation.NotationName = "PersonalData"; sspNotation.NotationValue = infos; spSelfSig.AddSubPacket(sspNotation,false); } if (!isRevocable) { SignatureSubPacket sspRevocable = new SignatureSubPacket(); sspRevocable.Type = SignatureSubPacketTypes.Revocable; sspRevocable.Revocable = isRevocable; spSelfSig.AddSubPacket(sspRevocable, true); } SignatureSubPacket sspPrimaryUID = new SignatureSubPacket(); sspPrimaryUID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUID.Revocable = false; spSelfSig.AddSubPacket(sspPrimaryUID, true); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = skpSignatureKey.PublicKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, tpkKey.PrimaryKey); tpkKey.Certifications.Add(cuiUID); tskKey.UserIDs.Add(uipUID); return; } throw new Exception("Keys not found"); }
/// <summary> /// Signs a key /// </summary> /// <param name="tspKey">key to be signed</param> /// <param name="cuidTobeSigned">user id to be signed</param> /// <param name="skpKeySigner">signer private key</param> /// <param name="strPassphrase">signer passphrase</param> /// <param name="exportable">exportable signature</param> /// <param name="expirationTime">expiration time (new DateTime(0) == never)</param> /// <param name="isRevocable"></param> public void SignKey(TransportablePublicKey tspKey, CertifiedUserID cuidTobeSigned, TransportableSecretKey skpKeySigner, string strPassphrase, bool exportable, DateTime expirationTime, bool isRevocable) { SignaturePacket spSig = new SignaturePacket(); spSig.Version = SignaturePacketVersionNumbers.v4; spSig.HashAlgorithm = HashAlgorithms.SHA1; spSig.KeyID = skpKeySigner.PrimaryKey.PublicKey.KeyID; spSig.TimeCreated = DateTime.Now; SignatureSubPacket sspExportableSignature = new SignatureSubPacket(); sspExportableSignature.Type = SignatureSubPacketTypes.ExportableSignature; sspExportableSignature.ExportableSignature = exportable; spSig.AddSubPacket(sspExportableSignature, false); if (!isRevocable) { SignatureSubPacket sspRevocable = new SignatureSubPacket(); sspRevocable.Type = SignatureSubPacketTypes.Revocable; sspRevocable.Revocable = isRevocable; spSig.AddSubPacket(sspRevocable, true); } if (expirationTime.Ticks != 0) { SignatureSubPacket sspExpiration = new SignatureSubPacket(); sspExpiration.Type = SignatureSubPacketTypes.KeyExpirationTime; sspExpiration.KeyExpirationTime = new DateTime(expirationTime.Ticks + (new DateTime(1970,1,2)).Ticks - tspKey.PrimaryKey.TimeCreated.Ticks); spSig.AddSubPacket(sspExpiration, true); } cuidTobeSigned.Sign(spSig, skpKeySigner.PrimaryKey, strPassphrase, tspKey.PrimaryKey); }
/// <summary> /// Sets the trust level and amount for a specified userID in a key /// </summary> /// <param name="userIdKeyId">KeyID of the key containing the userID which this set the trust of</param> /// <param name="userID">UserID whose trust has to be set</param> /// <param name="KeyID">Signer (Truster) keyID</param> /// <param name="strPassphrase">passphrase of the signer</param> /// <param name="trustLevel">trust level</param> /// <param name="trustAmount">trust amount</param> public void setUserIDTrust(ulong userIdKeyId, CertifiedUserID userID, ulong KeyID, string strPassphrase, int trustLevel, int trustAmount) { TransportablePublicKey tpkKey = this.PublicRing.Find(userIdKeyId,false); TransportableSecretKey tskKey = this.SecretRing.Find(KeyID); bool updated = false; if (tpkKey!=null && tskKey!=null) { ArrayList cert = new ArrayList(userID.Certificates); for (int k = 0; k < cert.Count; k++) { updated = false; SignaturePacket sp = (SignaturePacket)cert[k]; if ((sp.SignatureType == SignatureTypes.UserIDSignature || sp.SignatureType == SignatureTypes.UserIDSignature_CasualVerification || sp.SignatureType == SignatureTypes.UserIDSignature_NoVerification || sp.SignatureType == SignatureTypes.UserIDSignature_PositivVerification) && sp.KeyID == KeyID) { foreach (SignatureSubPacket ssp in sp.HashedSubPackets) { if(ssp.Type == SignatureSubPacketTypes.TrustSignature) { ssp.TrustLevel = (byte)(trustLevel & 0xFF); ssp.TrustAmount = (byte)(trustAmount & 0xFF); updated = true; } } if (!updated) { foreach (SignatureSubPacket ssp in sp.UnhashedSubPackets) { if (ssp.Type == SignatureSubPacketTypes.TrustSignature) { ssp.TrustLevel = (byte)(trustLevel & 0xFF); ssp.TrustAmount = (byte)(trustAmount & 0xFF); updated = true; } } } if(updated) { userID.Certificates.Remove(sp); userID.Sign(sp, tskKey.PrimaryKey, strPassphrase, tpkKey.PrimaryKey); updated = true; } else { SignatureSubPacket sspTrust = new SignatureSubPacket(); sspTrust.Type = SignatureSubPacketTypes.TrustSignature; sspTrust.TrustAmount = (byte)(trustAmount & 0xFF); sspTrust.TrustLevel = (byte)(trustLevel & 0xFF); sp.AddSubPacket(sspTrust, false); userID.Certificates.Remove(sp); userID.Sign(sp, tskKey.PrimaryKey, strPassphrase, tpkKey.PrimaryKey); updated = true; } } } } if (!updated) throw new Exception("User id not certified by this Key. You cannot set Trust."); }
/// <summary> /// Signes the data given as parameter with the given secret key. /// The given password has to fit the given key. /// </summary> /// <remarks> /// <para>The function calculates a message digest over the given signature /// data and signes the digest with the given key.</para> /// <para>The results of the signature operation are directly stored /// in the Signature property of this class.</para> /// </remarks> /// <param name="bSignedData">The data that is to be signed.</param> /// <param name="skpKey">The key that is to sign the data</param> /// <param name="strPassphrase">The passphrase that is neccessary to /// decrypt the given key.</param> public void Sign(byte[] bSignedData, SecretKeyPacket skpKey, string strPassphrase) { System.Security.Cryptography.HashAlgorithm haSigner; AsymmetricCipher acSigner; this.SignatureAlgorithm = skpKey.PublicKey.Algorithm; switch (this.HashAlgorithm) { case HashAlgorithms.MD5: haSigner = System.Security.Cryptography.MD5.Create(); break; case HashAlgorithms.SHA1: haSigner = System.Security.Cryptography.SHA1.Create(); break; default: throw(new System.Exception("Currently only MD5 and SHA1 are implemented as hash algorithms!")); } switch (this.SignatureAlgorithm) { case AsymAlgorithms.DSA: acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.DSA(); break; case AsymAlgorithms.RSA_Encrypt_Sign: case AsymAlgorithms.RSA_Sign_Only: acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.RSA(); break; default: throw(new System.Exception("Currently only DSA and RSA are implemented as signature algorithms!")); } byte[] bSignature = new byte[0]; int iCounter = 0; if (this.Version <= SignaturePacketVersionNumbers.v3) { bSignature = new byte[5]; bSignature[iCounter++] = (byte)this.SignatureType; long lTime = (dtTimeCreated.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000; bSignature[iCounter++] = (byte)((lTime >> 24) & 0xFF); bSignature[iCounter++] = (byte)((lTime >> 16) & 0xFF); bSignature[iCounter++] = (byte)((lTime >> 8) & 0xFF); bSignature[iCounter++] = (byte)(lTime & 0xFF); } else { // Add Issuer KeyID Subpacket if it's not there. try { ulong lTestForKeyID = this.KeyID; } catch (Exception) { SignatureSubPacket sspIssuerKeyID = new SignatureSubPacket(); sspIssuerKeyID.Type = SignatureSubPacketTypes.IssuerKeyID; sspIssuerKeyID.KeyID = this.lKeyID; this.AddSubPacket(sspIssuerKeyID, true); } // Add TimeCreated Subpacket if it's not there. try { this.FindSignatureCreationTime(); } catch (Exception) { SignatureSubPacket sspCreationTime = new SignatureSubPacket(); sspCreationTime.Type = SignatureSubPacketTypes.SignatureCreationTime; sspCreationTime.TimeCreated = DateTime.Now; this.AddSubPacket(sspCreationTime, true); } //Hashed Subpackets Length int lHashedSubPacketLength = 0; for (int i = 0; i < this.HashedSubPackets.Length; i++) { lHashedSubPacketLength += this.HashedSubPackets[i].Generate().Length; } bSignature = new byte[lHashedSubPacketLength + 12]; bSignature[iCounter++] = 4; // Version bSignature[iCounter++] = (byte)this.SignatureType; bSignature[iCounter++] = (byte)this.SignatureAlgorithm; bSignature[iCounter++] = (byte)this.HashAlgorithm; //Hashed bSignature[iCounter++] = (byte)((lHashedSubPacketLength >> 8) & 0xFF); bSignature[iCounter++] = (byte)(lHashedSubPacketLength & 0xFF); for (int i = 0; i < this.HashedSubPackets.Length; i++) { byte[] bSubPacket = this.HashedSubPackets[i].Generate(); Array.Copy(bSubPacket, 0, bSignature, iCounter, bSubPacket.Length); iCounter += bSubPacket.Length; } //Final Trailer of 6 bytes bSignature[iCounter++] = 0x04; bSignature[iCounter++] = 0xFF; bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 24) & 0xFF); bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 16) & 0xFF); bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 8) & 0xFF); bSignature[iCounter++] = (byte)((lHashedSubPacketLength + 6) & 0xFF); } byte[] bData = new byte[bSignedData.Length + bSignature.Length]; Array.Copy(bSignedData, bData, bSignedData.Length); Array.Copy(bSignature, 0, bData, bSignedData.Length, bSignature.Length); byte[] bHash = haSigner.ComputeHash(bData); BigInteger biHash = new BigInteger(bHash); //PKCS1 Encode the hash if (this.SignatureAlgorithm != AsymAlgorithms.DSA) { // We encode the MD in this way: // 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) // PAD consists of FF bytes. byte[] bASN = new byte[0]; switch (this.HashAlgorithm) { case HashAlgorithms.MD5: bASN = new byte[] { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; break; case HashAlgorithms.SHA1: bASN = new byte[] { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 }; break; } int iFrameSize = (skpKey.PublicKey.KeyMaterial[0].bitCount() + 7) / 8; byte[] bFrame = new byte[iFrameSize]; int iASNCounter = 0; bFrame[iASNCounter++] = 0; bFrame[iASNCounter++] = 1; int iFFLength = iFrameSize - bHash.Length - bASN.Length - 3; for (int i = 0; i < iFFLength; i++) { bFrame[iASNCounter++] = 0xFF; } bFrame[iASNCounter++] = 0; Array.Copy(bASN, 0, bFrame, iASNCounter, bASN.Length); iASNCounter += bASN.Length; Array.Copy(bHash, 0, bFrame, iASNCounter, bHash.Length); biHash = new BigInteger(bFrame); } sSignedHash16Bit = (ushort)((bHash[0] << 8) + bHash[1]); biSignature = acSigner.Sign(biHash, skpKey, strPassphrase); this.bIsUpdated = true; }
/// <summary> /// Revokes a key certified userID /// </summary> /// <param name="KeyID">key containing the certified user id</param> /// <param name="cuidTobeSigned">certified user id to be revoked</param> /// <param name="skpKeySigner">revoker secret key</param> /// <param name="strPassphrase">revoker passphrase</param> /// <param name="exportable">exportable revocation</param> public void RevokeKeyCertificate(ulong KeyID, CertifiedUserID cuidTobeSigned, TransportableSecretKey skpKeySigner, string strPassphrase, bool exportable) { TransportablePublicKey tspKey = this.PublicRing.Find(KeyID,false); if(tspKey == null) throw new Exception("Public Key not found"); bool found = false; CertifiedUserID toBeVerified = null; foreach(CertifiedUserID cui in tspKey.Certifications) { if(cui==cuidTobeSigned) { found=true; toBeVerified = cui; break; } } if (!found) throw new Exception("UserId not found among Key certificates"); found = false; foreach(SignaturePacket sign in toBeVerified.Certificates) { if(sign.KeyID == skpKeySigner.PrimaryKey.PublicKey.KeyID && sign.isRevocable()) found = true; } if (!found) throw new Exception("UserId not certified by this private key or not revocable"); SignaturePacket spSig = new SignaturePacket(); spSig.Version = SignaturePacketVersionNumbers.v4; spSig.HashAlgorithm = HashAlgorithms.SHA1; spSig.KeyID = skpKeySigner.PrimaryKey.PublicKey.KeyID; spSig.TimeCreated = DateTime.Now; SignatureSubPacket sspExportableSignature = new SignatureSubPacket(); sspExportableSignature.Type = SignatureSubPacketTypes.ExportableSignature; sspExportableSignature.ExportableSignature = exportable; spSig.AddSubPacket(sspExportableSignature, false); cuidTobeSigned.Revoke(spSig, skpKeySigner.PrimaryKey, strPassphrase, tspKey.PrimaryKey); }
/// <summary> /// Generate a key pair /// </summary> /// <param name="iKeySize">Encription key size</param> /// <param name="strPassphrase">passhrase for the key pair</param> /// <param name="userID">primary user id</param> /// <param name="email">user email</param> /// <param name="notation">xml encoded user info</param> /// <param name="expirationTime">expiration date of the primary key (new DateTime(0) == never)</param> /// <param name="keyType">1: RSA/DSA 0:Elgamal/DSA(DEFAULT)</param> /// <param name="isRevocableKey">revocable?</param> /// <param name="isRevocableSubkey">revocable subkey?</param> public void GenerateKey(int iKeySize, string strPassphrase, string userID, string email, string notation, DateTime expirationTime, int keyType, bool isRevocableKey, bool isRevocableSubkey) { if(iKeySize % 1024 != 0) throw new Exception("Keysize must be a 1024 multiple"); System.Security.Cryptography.RandomNumberGenerator rngRand; // let's first create the encryption key BigInteger[][] biEncryptionKey; if (keyType == 1) { // it's a RSA/DSA key biEncryptionKey = GenerateRSAEncryptionKey(iKeySize); } else { // it's an elgamal/DSA key DEFAULF biEncryptionKey = GenerateElGamalEncryptionKey(iKeySize); } // now the signature key BigInteger[][] biSignatureKey = GenerateDSASignatureKey(); PublicKeyPacket pkpSignatureKey = new PublicKeyPacket(false); pkpSignatureKey.Algorithm = AsymAlgorithms.DSA; pkpSignatureKey.KeyMaterial = biSignatureKey[0]; pkpSignatureKey.TimeCreated = DateTime.Now; pkpSignatureKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpSignatureKey = new SecretKeyPacket(false); skpSignatureKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpSignatureKey.PublicKey = pkpSignatureKey; skpSignatureKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); rngRand.GetBytes(skpSignatureKey.InitialVector); skpSignatureKey.EncryptKeyMaterial(biSignatureKey[1], strPassphrase); skpSignatureKey.PublicKey = pkpSignatureKey; PublicKeyPacket pkpEncryptionKey = new PublicKeyPacket(true); if (keyType == 0) { // it's an elgamal/DSA key pkpEncryptionKey.Algorithm = AsymAlgorithms.ElGamal_Encrypt_Only; } else if (keyType == 1) { // it's a RSA/DSA key pkpEncryptionKey.Algorithm = AsymAlgorithms.RSA_Encrypt_Only; } pkpEncryptionKey.KeyMaterial = biEncryptionKey[0]; pkpEncryptionKey.TimeCreated = DateTime.Now; pkpEncryptionKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpEncryptionKey = new SecretKeyPacket(true); skpEncryptionKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpEncryptionKey.PublicKey = pkpEncryptionKey; skpEncryptionKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); rngRand.GetBytes(skpEncryptionKey.InitialVector); skpEncryptionKey.EncryptKeyMaterial(biEncryptionKey[1], strPassphrase); skpEncryptionKey.PublicKey = pkpEncryptionKey; CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = userID.Trim() + " <" + email.Trim() + ">"; cuiUID.UserID = uipUID; SignaturePacket spSelfSig = new SignaturePacket(); if (notation != null) { SignatureSubPacket sspNotation = new SignatureSubPacket(); sspNotation.Type = SignatureSubPacketTypes.NotationData; sspNotation.NotationName = "PersonalData"; sspNotation.NotationValue = notation; spSelfSig.AddSubPacket(sspNotation,false); } if (expirationTime.Ticks != 0) { SignatureSubPacket sspExpiration = new SignatureSubPacket(); sspExpiration.Type = SignatureSubPacketTypes.KeyExpirationTime; sspExpiration.KeyExpirationTime = new DateTime(expirationTime.Ticks + (new DateTime(1970,1,2)).Ticks - pkpEncryptionKey.TimeCreated.Ticks); spSelfSig.AddSubPacket(sspExpiration, true); } if (!isRevocableKey) { SignatureSubPacket sspRevocable = new SignatureSubPacket(); sspRevocable.Type = SignatureSubPacketTypes.Revocable; sspRevocable.Revocable = isRevocableKey; spSelfSig.AddSubPacket(sspRevocable, true); } SignatureSubPacket sspPrimaryUID = new SignatureSubPacket(); sspPrimaryUID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUID.Revocable = true; spSelfSig.AddSubPacket(sspPrimaryUID, true); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = pkpSignatureKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; SignatureSubPacket sspPrimaryUserID = new SignatureSubPacket(); sspPrimaryUserID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUserID.PrimaryUserID = true; spSelfSig.AddSubPacket(sspPrimaryUserID, true); SignatureSubPacket sspPreferedSymAlgos = new SignatureSubPacket(); sspPreferedSymAlgos.Type = SignatureSubPacketTypes.PreferedSymmetricAlgorithms; sspPreferedSymAlgos.PreferedSymAlgos = new SymAlgorithms[] {SymAlgorithms.AES256, SymAlgorithms.AES192, SymAlgorithms.AES256, SymAlgorithms.CAST5, SymAlgorithms.Triple_DES}; spSelfSig.AddSubPacket(sspPreferedSymAlgos, true); SignatureSubPacket sspPreferedHashAlgos = new SignatureSubPacket(); sspPreferedHashAlgos.Type = SignatureSubPacketTypes.PreferedHashAlgorithms; sspPreferedHashAlgos.PreferedHashAlgos = new HashAlgorithms[] {HashAlgorithms.SHA1}; spSelfSig.AddSubPacket(sspPreferedHashAlgos, true); cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, pkpSignatureKey); CertifiedPublicSubkey cpsEncryptionKey = new CertifiedPublicSubkey(); cpsEncryptionKey.Subkey = pkpEncryptionKey; cpsEncryptionKey.SignKeyBindingSignature(pkpSignatureKey, skpSignatureKey, strPassphrase, expirationTime, isRevocableSubkey); TransportablePublicKey tpkPublicKey = new TransportablePublicKey(); tpkPublicKey.PrimaryKey = pkpSignatureKey; tpkPublicKey.SubKeys.Add(cpsEncryptionKey); tpkPublicKey.Certifications.Add(cuiUID); this.PublicRing.AddPublicKey(tpkPublicKey); TransportableSecretKey tskSecretKey = new TransportableSecretKey(); tskSecretKey.PrimaryKey = skpSignatureKey; tskSecretKey.SubKeys.Add(skpEncryptionKey); tskSecretKey.UserIDs.Add(uipUID); this.SecretRing.AddSecretKey(tskSecretKey); }
public void SignKey(ulong lSignedKeyID, ulong lSigningKeyID, string strUserID, int nIntroducerDepth, bool bIsExportable, int nType, string strPassphrase) { TransportableSecretKey tskKey = skrKeyRing.Find(lSigningKeyID); SecretKeyPacket skpSignatureKey = tskKey.FindKey(AsymActions.Sign); TransportablePublicKey tpkKey = pkrKeyRing.Find(lSignedKeyID, false); SignaturePacket spCertificate = new SignaturePacket(); spCertificate.SignatureType = (SignatureTypes)nType; spCertificate.Version = SignaturePacketVersionNumbers.v4; spCertificate.HashAlgorithm = HashAlgorithms.SHA1; spCertificate.KeyID = skpSignatureKey.PublicKey.KeyID; spCertificate.TimeCreated = DateTime.Now; CertifiedUserID cuiID = null; IEnumerator ieUserIDs = tpkKey.Certifications.GetEnumerator(); while (ieUserIDs.MoveNext()) { if (!(ieUserIDs.Current is CertifiedUserID)) continue; CertifiedUserID cuiThisID = (CertifiedUserID)ieUserIDs.Current; if (cuiThisID.ToString() == strUserID) { cuiID = cuiThisID; } } if (cuiID == null) throw new Exception("UserID could not be found!"); if (bIsExportable == false) { SignatureSubPacket sspNotExportable = new SignatureSubPacket(); sspNotExportable.Type = SignatureSubPacketTypes.ExportableSignature; sspNotExportable.ExportableSignature = false; spCertificate.AddSubPacket(sspNotExportable, true); } if (nIntroducerDepth > 0) { SignatureSubPacket sspTrust = new SignatureSubPacket(); sspTrust.Type = SignatureSubPacketTypes.TrustSignature; sspTrust.TrustLevel = (byte)nIntroducerDepth; sspTrust.TrustAmount = 120; spCertificate.AddSubPacket(sspTrust, true); } cuiID.Sign(spCertificate, skpSignatureKey, strPassphrase, tpkKey.PrimaryKey); tpkKey.Certifications.Remove(cuiID); tpkKey.Certifications.Add(cuiID); pkrKeyRing.Delete(lSignedKeyID); pkrKeyRing.AddPublicKey(tpkKey); pkrKeyRing.Save(); }
public void GenerateKey(string strName, string strEmail, string strKeyType, int iKeySize, long lExpiration, string strPassphrase) { if (strKeyType == "ElGamal/DSA") { System.Security.Cryptography.RandomNumberGenerator rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); // let's first create the encryption key BigInteger[][] biEncryptionKey = GenerateEncryptionKey(iKeySize); // now the signature key BigInteger[][] biSignatureKey = GenerateSignatureKey(); PublicKeyPacket pkpSignatureKey = new PublicKeyPacket(false); pkpSignatureKey.Algorithm = AsymAlgorithms.DSA; pkpSignatureKey.KeyMaterial = biSignatureKey[0]; pkpSignatureKey.TimeCreated = DateTime.Now; pkpSignatureKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpSignatureKey = new SecretKeyPacket(false); skpSignatureKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpSignatureKey.PublicKey = pkpSignatureKey; skpSignatureKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand.GetBytes(skpSignatureKey.InitialVector); skpSignatureKey.EncryptKeyMaterial(biSignatureKey[1], strPassphrase); skpSignatureKey.PublicKey = pkpSignatureKey; PublicKeyPacket pkpEncryptionKey = new PublicKeyPacket(true); pkpEncryptionKey.Algorithm = AsymAlgorithms.ElGamal_Encrypt_Only; pkpEncryptionKey.KeyMaterial = biEncryptionKey[0]; pkpEncryptionKey.TimeCreated = DateTime.Now; pkpEncryptionKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpEncryptionKey = new SecretKeyPacket(true); skpEncryptionKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpEncryptionKey.PublicKey = pkpEncryptionKey; skpEncryptionKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand.GetBytes(skpEncryptionKey.InitialVector); skpEncryptionKey.EncryptKeyMaterial(biEncryptionKey[1], strPassphrase); skpEncryptionKey.PublicKey = pkpEncryptionKey; CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = strName.Trim() + " <" + strEmail.Trim() + ">"; cuiUID.UserID = uipUID; SignaturePacket spSelfSig = new SignaturePacket(); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = pkpSignatureKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; SignatureSubPacket sspPrimaryUserID = new SignatureSubPacket(); sspPrimaryUserID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUserID.PrimaryUserID = true; spSelfSig.AddSubPacket(sspPrimaryUserID, true); SignatureSubPacket sspPreferedSymAlgos = new SignatureSubPacket(); sspPreferedSymAlgos.Type = SignatureSubPacketTypes.PreferedSymmetricAlgorithms; sspPreferedSymAlgos.PreferedSymAlgos = new SymAlgorithms[] {SymAlgorithms.AES256, SymAlgorithms.AES192, SymAlgorithms.AES256, SymAlgorithms.CAST5, SymAlgorithms.Triple_DES}; spSelfSig.AddSubPacket(sspPreferedSymAlgos, true); SignatureSubPacket sspPreferedHashAlgos = new SignatureSubPacket(); sspPreferedHashAlgos.Type = SignatureSubPacketTypes.PreferedHashAlgorithms; sspPreferedHashAlgos.PreferedHashAlgos = new HashAlgorithms[] {HashAlgorithms.SHA1}; spSelfSig.AddSubPacket(sspPreferedHashAlgos, true); if (lExpiration != 0) { SignatureSubPacket sspExpiration = new SignatureSubPacket(); sspExpiration.Type = SignatureSubPacketTypes.SignatureExpirationTime; sspExpiration.SignatureExpirationTime = new DateTime(lExpiration); spSelfSig.AddSubPacket(sspExpiration, true); } cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, pkpSignatureKey); CertifiedPublicSubkey cpsEncryptionKey = new CertifiedPublicSubkey(); cpsEncryptionKey.Subkey = pkpEncryptionKey; cpsEncryptionKey.SignKeyBindingSignature(pkpSignatureKey, skpSignatureKey, strPassphrase, new DateTime(lExpiration), true); TransportablePublicKey tpkPublicKey = new TransportablePublicKey(); tpkPublicKey.PrimaryKey = pkpSignatureKey; tpkPublicKey.SubKeys.Add(cpsEncryptionKey); tpkPublicKey.Certifications.Add(cuiUID); TransportableSecretKey tskSecretKey = new TransportableSecretKey(); tskSecretKey.PrimaryKey = skpSignatureKey; tskSecretKey.SubKeys.Add(skpEncryptionKey); tskSecretKey.UserIDs.Add(uipUID); this.pkrKeyRing.AddPublicKey(tpkPublicKey); this.skrKeyRing.AddSecretKey(tskSecretKey); pkrKeyRing.Save(); skrKeyRing.Save(); // it's an RSA key } else if (strKeyType == "RSA") { } }
public SignatureSubPacket[] ParsePackets(byte[] bBinaryData) { ArrayList alPackets = new ArrayList(100); byte[] bTmpData = new byte[bBinaryData.Length]; Array.Copy(bBinaryData, bTmpData, bBinaryData.Length); long iCurrentIndex = 0; while (iCurrentIndex < bBinaryData.Length) { SignatureSubPacket pTmpPacket = new SignatureSubPacket(); SignatureSubPacket pCurrentPacket = pTmpPacket.ParsePacket(bTmpData); iCurrentIndex += pCurrentPacket.Length; alPackets.Add(pCurrentPacket); bTmpData = new byte[bTmpData.Length - pCurrentPacket.Length]; Array.Copy(bBinaryData, (int)iCurrentIndex, bTmpData, 0, bBinaryData.Length - (int)iCurrentIndex); } SignatureSubPacket[] pReturnPackets = new SignatureSubPacket[alPackets.Count]; IEnumerator iePacketEnum = alPackets.GetEnumerator(); int iCount = 0; while (iePacketEnum.MoveNext()) { pReturnPackets[iCount++] = (SignatureSubPacket)iePacketEnum.Current; } return pReturnPackets; }
/// <summary> /// Parses the packet given as byte array into the current /// class and returns this with the populated parameters. /// </summary> /// <param name="bData">A byte array containing an OpenPGP /// representation of the packet.</param> /// <returns>Returns an SignaturePacket that containes /// the parsed properties.</returns> /// <remarks>No remarks</remarks> public override Packet ParsePacket(byte[] bData) { Version = (SignaturePacketVersionNumbers)bData[0]; if (Version == SignaturePacketVersionNumbers.v3) { SignatureType = (SignatureTypes)bData[2]; long iTime = (long)bData[3] << 24; iTime ^= (long)bData[4] << 16; iTime ^= (long)bData[5] << 8; iTime ^= (long)bData[6]; TimeCreated = new DateTime(iTime * 10000000 + new DateTime(1970, 1, 1).Ticks); lKeyID = (ulong)bData[7] << 56; lKeyID ^= (ulong)bData[8] << 48; lKeyID ^= (ulong)bData[9] << 40; lKeyID ^= (ulong)bData[10] << 32; lKeyID ^= (ulong)bData[11] << 24; lKeyID ^= (ulong)bData[12] << 16; lKeyID ^= (ulong)bData[13] << 8; lKeyID ^= (ulong)bData[14]; SignatureAlgorithm = (AsymAlgorithms)bData[15]; HashAlgorithm = (HashAlgorithms)bData[16]; HashedSubPackets = new SignatureSubPacket[0]; UnhashedSubPackets = new SignatureSubPacket[0]; sSignedHash16Bit = (ushort)(bData[17] << 8); sSignedHash16Bit ^= (ushort)(bData[18]); byte[] bMPIs = new byte[bData.Length - 19]; Array.Copy(bData, 19, bMPIs, 0, bMPIs.Length); Signature = BigInteger.ParseMPIs(bMPIs); } else if (Version == SignaturePacketVersionNumbers.v4) { SignatureType = (SignatureTypes)bData[1]; SignatureAlgorithm = (AsymAlgorithms)bData[2]; HashAlgorithm = (HashAlgorithms)bData[3]; int iHashedSubPacketLength = (bData[4] << 8) ^ (bData[5]); byte[] bHashedSubPackets = new byte[iHashedSubPacketLength]; Array.Copy(bData, 6, bHashedSubPackets, 0, iHashedSubPacketLength); SignatureSubPacket sspSubPacketParser = new SignatureSubPacket(); sspHashedSubPackets = sspSubPacketParser.ParsePackets(bHashedSubPackets); for (int i = 0; i < sspHashedSubPackets.Length; i++) { if (sspHashedSubPackets[i].Type == SignatureSubPacketTypes.IssuerKeyID) { this.KeyID = sspHashedSubPackets[i].KeyID; } else if (sspHashedSubPackets[i].Type == SignatureSubPacketTypes.SignatureCreationTime) { this.TimeCreated = sspHashedSubPackets[i].TimeCreated; } } int iIndex = iHashedSubPacketLength + 6; bHashedPart = new byte[iIndex]; Array.Copy(bData, 0, bHashedPart, 0, iIndex); int iUnhashedSubPacketLength = (bData[iIndex++] << 8) ^ bData[iIndex++]; byte[] bUnhashedSubPackets = new byte[iUnhashedSubPacketLength]; Array.Copy(bData, iIndex, bUnhashedSubPackets, 0, iUnhashedSubPacketLength); sspSubPacketParser = new SignatureSubPacket(); sspUnhashedSubPackets = sspSubPacketParser.ParsePackets(bUnhashedSubPackets); for (int i = 0; i < sspUnhashedSubPackets.Length; i++) { if (sspUnhashedSubPackets[i].Type == SignatureSubPacketTypes.IssuerKeyID) { this.KeyID = sspUnhashedSubPackets[i].KeyID; } else if (sspUnhashedSubPackets[i].Type == SignatureSubPacketTypes.SignatureCreationTime) { this.TimeCreated = sspUnhashedSubPackets[i].TimeCreated; } } iIndex += iUnhashedSubPacketLength; sSignedHash16Bit = (ushort)(bData[iIndex++] << 8); sSignedHash16Bit ^= (ushort)(bData[iIndex++]); byte[] bMPIs = new byte[bData.Length - iIndex]; Array.Copy(bData, iIndex, bMPIs, 0, bMPIs.Length); Signature = BigInteger.ParseMPIs(bMPIs); } this.bIsUpdated = false; return(this); }
/// <summary> /// Changes the primary user id of a public key /// </summary> /// <param name="newPUID">the certified user id to se as primary</param> /// <param name="KeyID">the keyID to execute the operation for</param> /// <param name="strPassphrase"></param> public void changePrimaryUserID(CertifiedUserID newPUID, ulong KeyID, string strPassphrase) { TransportablePublicKey tpkKey = this.PublicRing.Find(KeyID,false); TransportableSecretKey tskKey = this.SecretRing.Find(KeyID); if (tpkKey!=null && tskKey!=null) { CertifiedUserID oldPUID = tpkKey.PrimaryUserIDCert; if (oldPUID!=newPUID) { bool updated = false; for (int k = 0; k < oldPUID.Certificates.Count; k++) { SignaturePacket sp = (SignaturePacket)oldPUID.Certificates[k]; if(sp.SignatureType == SignatureTypes.UserIDSignature || sp.SignatureType == SignatureTypes.UserIDSignature_CasualVerification || sp.SignatureType == SignatureTypes.UserIDSignature_NoVerification || sp.SignatureType == SignatureTypes.UserIDSignature_PositivVerification) { foreach (SignatureSubPacket ssp in sp.HashedSubPackets) { if(ssp.Type == SignatureSubPacketTypes.PrimaryUserID) { ssp.PrimaryUserID = false; updated = true; } } if (!updated) { foreach(SignatureSubPacket ssp in sp.UnhashedSubPackets) { if(ssp.Type == SignatureSubPacketTypes.PrimaryUserID) { ssp.PrimaryUserID = false; updated = true; } } } if (updated) { oldPUID.Certificates.Remove(sp); oldPUID.Sign(sp, tskKey.PrimaryKey, strPassphrase, tpkKey.PrimaryKey); break; } } } updated = false; for (int k = 0; k < oldPUID.Certificates.Count; k++) { SignaturePacket sp = (SignaturePacket)newPUID.Certificates[k]; if (sp.SignatureType == SignatureTypes.UserIDSignature || sp.SignatureType == SignatureTypes.UserIDSignature_CasualVerification || sp.SignatureType == SignatureTypes.UserIDSignature_NoVerification || sp.SignatureType == SignatureTypes.UserIDSignature_PositivVerification) { foreach(SignatureSubPacket ssp in sp.HashedSubPackets) { if(ssp.Type == SignatureSubPacketTypes.PrimaryUserID) { ssp.PrimaryUserID = true; updated = true; } } if (!updated) { foreach (SignatureSubPacket ssp in sp.UnhashedSubPackets) { if (ssp.Type == SignatureSubPacketTypes.PrimaryUserID) { ssp.PrimaryUserID = true; updated = true; } } } if (updated) { newPUID.Certificates.Remove(sp); newPUID.Sign(sp, tskKey.PrimaryKey, strPassphrase, tpkKey.PrimaryKey); break; } if (!updated) { SignatureSubPacket sspPrimaryUserID = new SignatureSubPacket(); sspPrimaryUserID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUserID.PrimaryUserID = true; sp.AddSubPacket(sspPrimaryUserID,true); newPUID.Certificates.Remove(sp); newPUID.Sign(sp, tskKey.PrimaryKey, strPassphrase, tpkKey.PrimaryKey); break; } } } } } }
/// <summary> /// Text signing /// </summary> /// <param name="strMessage">text to be signed</param> /// <param name="tskKey">secret key for signing purpose</param> /// <param name="strPassphrase">passphrase for the secret key</param> /// <returns>the signed text</returns> public string ClearTextSign(string strMessage, TransportableSecretKey tskKey, string strPassphrase, bool embedMessage) { SignaturePacket spSign = new SignaturePacket(); strMessage = Radix64.TrimMessage(strMessage); SecretKeyPacket skpKey = tskKey.FindKey(AsymActions.Sign); spSign.HashAlgorithm = HashAlgorithms.SHA1; spSign.Format = PacketFormats.New; SignatureSubPacket sspCreator = new SignatureSubPacket(); sspCreator.Type = SignatureSubPacketTypes.IssuerKeyID; sspCreator.KeyID = skpKey.PublicKey.KeyID; SignatureSubPacket sspCreationTime = new SignatureSubPacket(); sspCreationTime.Type = SignatureSubPacketTypes.SignatureCreationTime; sspCreationTime.TimeCreated = DateTime.Now; spSign.HashedSubPackets = new SignatureSubPacket[2]; spSign.HashedSubPackets[0] = sspCreator; spSign.HashedSubPackets[1] = sspCreationTime; //spSign.KeyID = skpKey.PublicKey.KeyID; //spSign.TimeCreated = DateTime.Now; spSign.SignatureAlgorithm = skpKey.PublicKey.Algorithm; spSign.SignatureType = SignatureTypes.TextSignature; spSign.Version = SignaturePacketVersionNumbers.v4; byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(strMessage); spSign.Sign(bMessage, skpKey, strPassphrase); byte[] bSignature = spSign.Generate(); string strSignature = Radix64.Encode(bSignature, true); string strFinal; if(embedMessage) strFinal = Armor.WrapCleartextSignature(strMessage, strSignature); else strFinal = Armor.WrapCleartextSignature(strSignature); return strFinal; }
/// <summary> /// Revoke a key /// </summary> /// <param name="KeyID">key to be revoked</param> /// <param name="skpKeySigner">revoker secret key</param> /// <param name="strPassphrase">revoker passphrase</param> /// <param name="exportable">exportable revocation</param> public void RevokeKey(ulong KeyID, TransportableSecretKey skpKeySigner, string strPassphrase, bool exportable) { TransportablePublicKey tspKey = this.PublicRing.Find(KeyID,false); if (tspKey == null) throw new Exception("Public Key not found"); if (this.PublicRing.isRevoked(KeyID)) throw new Exception("Public Key alreadyRevoked"); if (tspKey.PrimaryKey.KeyID != KeyID) throw new Exception("This is not a Primary key... use Revoke Subkey method instead"); foreach (SignaturePacket sign in tspKey.PrimaryUserIDCert.Certificates) { if (!sign.isRevocable()) return; } bool isRevokerKey = false; if (KeyID == skpKeySigner.PrimaryKey.PublicKey.KeyID) { isRevokerKey = true; } else { foreach (SignaturePacket spPacket in tspKey.RevocationKeys) { foreach (BigInteger revoker in spPacket.FindRevokerKeys()) { if (revoker.ToString() == skpKeySigner.PrimaryKey.PublicKey.Fingerprint.ToString()) { isRevokerKey = true; } } } } if (!isRevokerKey) throw new Exception("You cannot revoke this key"); SignaturePacket spSig = new SignaturePacket(); spSig.Version = SignaturePacketVersionNumbers.v4; spSig.HashAlgorithm = HashAlgorithms.SHA1; spSig.KeyID = skpKeySigner.PrimaryKey.PublicKey.KeyID; spSig.TimeCreated = DateTime.Now; SignatureSubPacket sspExportableSignature = new SignatureSubPacket(); sspExportableSignature.Type = SignatureSubPacketTypes.ExportableSignature; sspExportableSignature.ExportableSignature = exportable; spSig.AddSubPacket(sspExportableSignature, false); PublicKeyPacket pkpKey = tspKey.PrimaryKey; byte[] key = new byte[tspKey.PrimaryKey.Length]; tspKey.PrimaryKey.Header.CopyTo(key,0); tspKey.PrimaryKey.Body.CopyTo(key,tspKey.PrimaryKey.Header.Length); spSig.SignatureType = SignatureTypes.KeyRevocationSignature; spSig.Sign(key, skpKeySigner.PrimaryKey, strPassphrase); tspKey.RevocationSignatures.Add(spSig); }
/// <summary> /// Parses the packet given as byte array into the current /// class and returns this with the populated parameters. /// </summary> /// <param name="bData">A byte array containing an OpenPGP /// representation of the packet.</param> /// <returns>Returns an SignaturePacket that containes /// the parsed properties.</returns> /// <remarks>No remarks</remarks> public override Packet ParsePacket(byte[] bData) { Version = (SignaturePacketVersionNumbers)bData[0]; if (Version == SignaturePacketVersionNumbers.v3) { SignatureType = (SignatureTypes)bData[2]; long iTime = (long)bData[3] << 24; iTime ^= (long)bData[4] << 16; iTime ^= (long)bData[5] << 8; iTime ^= (long)bData[6]; TimeCreated = new DateTime(iTime*10000000 + new DateTime(1970, 1, 1).Ticks); lKeyID = (ulong)bData[7] << 56; lKeyID ^= (ulong)bData[8] << 48; lKeyID ^= (ulong)bData[9] << 40; lKeyID ^= (ulong)bData[10] << 32; lKeyID ^= (ulong)bData[11] << 24; lKeyID ^= (ulong)bData[12] << 16; lKeyID ^= (ulong)bData[13] << 8; lKeyID ^= (ulong)bData[14]; SignatureAlgorithm = (AsymAlgorithms)bData[15]; HashAlgorithm = (HashAlgorithms)bData[16]; HashedSubPackets = new SignatureSubPacket[0]; UnhashedSubPackets = new SignatureSubPacket[0]; sSignedHash16Bit = (ushort)(bData[17] << 8); sSignedHash16Bit ^= (ushort)(bData[18]); byte[] bMPIs = new byte[bData.Length - 19]; Array.Copy(bData, 19, bMPIs, 0, bMPIs.Length); Signature = BigInteger.ParseMPIs(bMPIs); } else if (Version == SignaturePacketVersionNumbers.v4) { SignatureType = (SignatureTypes)bData[1]; SignatureAlgorithm = (AsymAlgorithms)bData[2]; HashAlgorithm = (HashAlgorithms)bData[3]; int iHashedSubPacketLength = (bData[4] << 8) ^ (bData[5]); byte[] bHashedSubPackets = new byte[iHashedSubPacketLength]; Array.Copy(bData, 6, bHashedSubPackets, 0, iHashedSubPacketLength); SignatureSubPacket sspSubPacketParser = new SignatureSubPacket(); sspHashedSubPackets = sspSubPacketParser.ParsePackets(bHashedSubPackets); for (int i=0; i<sspHashedSubPackets.Length; i++) { if (sspHashedSubPackets[i].Type == SignatureSubPacketTypes.IssuerKeyID) { this.KeyID = sspHashedSubPackets[i].KeyID; } else if (sspHashedSubPackets[i].Type == SignatureSubPacketTypes.SignatureCreationTime) { this.TimeCreated = sspHashedSubPackets[i].TimeCreated; } } int iIndex = iHashedSubPacketLength + 6; bHashedPart = new byte[iIndex]; Array.Copy(bData, 0, bHashedPart, 0, iIndex); int iUnhashedSubPacketLength = (bData[iIndex++] << 8) ^ bData[iIndex++]; byte[] bUnhashedSubPackets = new byte[iUnhashedSubPacketLength]; Array.Copy(bData, iIndex, bUnhashedSubPackets, 0, iUnhashedSubPacketLength); sspSubPacketParser = new SignatureSubPacket(); sspUnhashedSubPackets = sspSubPacketParser.ParsePackets(bUnhashedSubPackets); for (int i=0; i<sspUnhashedSubPackets.Length; i++) { if (sspUnhashedSubPackets[i].Type == SignatureSubPacketTypes.IssuerKeyID) { this.KeyID = sspUnhashedSubPackets[i].KeyID; } else if (sspUnhashedSubPackets[i].Type == SignatureSubPacketTypes.SignatureCreationTime) { this.TimeCreated = sspUnhashedSubPackets[i].TimeCreated; } } iIndex += iUnhashedSubPacketLength; sSignedHash16Bit = (ushort)(bData[iIndex++] << 8); sSignedHash16Bit ^= (ushort)(bData[iIndex++]); byte[] bMPIs = new byte[bData.Length - iIndex]; Array.Copy(bData, iIndex, bMPIs, 0, bMPIs.Length); Signature = BigInteger.ParseMPIs(bMPIs); } this.bIsUpdated = false; return this; }
/// <summary> /// Revoke a subkey /// </summary> /// <param name="KeyID">subkey ID</param> /// <param name="skpKeySigner">revoker secret key</param> /// <param name="strPassphrase">revoker passphrase</param> /// <param name="exportable">exportable revocation</param> public void RevokeSubKey(ulong KeyID, TransportableSecretKey skpKeySigner, string strPassphrase, bool exportable) { TransportablePublicKey tspKey = this.PublicRing.Find(KeyID,false); if(tspKey == null) throw new Exception("Public Key not found"); if(tspKey.PrimaryKey.KeyID == KeyID) throw new Exception("This is a primary key... use RevokeKey method instead."); CertifiedPublicSubkey cps = null; foreach(CertifiedPublicSubkey cpsi in tspKey.SubKeys) { if(cpsi.Subkey.KeyID == KeyID) cps = cpsi; } bool allowed = false; ulong issuer = skpKeySigner.PrimaryKey.PublicKey.KeyID; if(issuer == tspKey.PrimaryKey.KeyID) { allowed = true; } else { foreach (SignaturePacket spPacket in tspKey.RevocationKeys) { foreach (BigInteger revoker in spPacket.FindRevokerKeys()) { if (revoker.ToString() == skpKeySigner.PrimaryKey.PublicKey.Fingerprint.ToString()) { allowed = true; } } } } if (allowed && cps.KeyBindingSignature.isRevocable()) { if (this.PublicRing.isRevoked(KeyID)) throw new Exception("Public SubKey alreadyRevoked"); SignaturePacket spSig = new SignaturePacket(); spSig.Version = SignaturePacketVersionNumbers.v4; spSig.HashAlgorithm = HashAlgorithms.SHA1; spSig.KeyID = skpKeySigner.PrimaryKey.PublicKey.KeyID; spSig.TimeCreated = DateTime.Now; SignatureSubPacket sspExportableSignature = new SignatureSubPacket(); sspExportableSignature.Type = SignatureSubPacketTypes.ExportableSignature; sspExportableSignature.ExportableSignature = exportable; spSig.AddSubPacket(sspExportableSignature, false); byte[] subkey = new byte[cps.Subkey.Length]; cps.Subkey.Header.CopyTo(subkey,0); cps.Subkey.Body.CopyTo(subkey,cps.Subkey.Header.Length); subkey[0]=0x99; byte[] mainkey = new byte[tspKey.PrimaryKey.Length]; tspKey.PrimaryKey.Header.CopyTo(mainkey,0); tspKey.PrimaryKey.Body.CopyTo(mainkey,tspKey.PrimaryKey.Header.Length); byte[] key = new byte[subkey.Length+mainkey.Length]; mainkey.CopyTo(key,0); subkey.CopyTo(key,mainkey.Length); spSig.SignatureType = SignatureTypes.SubkeyRevocationSignature; spSig.Sign(key, skpKeySigner.PrimaryKey, strPassphrase); cps.RevocationSignature=spSig; } else throw new Exception("Not allowed to revoke this subkey"); }
/// <summary> /// Signes the data given as parameter with the given secret key. /// The given password has to fit the given key. /// </summary> /// <remarks> /// <para>The function calculates a message digest over the given signature /// data and signes the digest with the given key.</para> /// <para>The results of the signature operation are directly stored /// in the Signature property of this class.</para> /// </remarks> /// <param name="bSignedData">The data that is to be signed.</param> /// <param name="skpKey">The key that is to sign the data</param> /// <param name="strPassphrase">The passphrase that is neccessary to /// decrypt the given key.</param> public void Sign(byte[] bSignedData, SecretKeyPacket skpKey, string strPassphrase) { System.Security.Cryptography.HashAlgorithm haSigner; AsymmetricCipher acSigner; this.SignatureAlgorithm = skpKey.PublicKey.Algorithm; switch (this.HashAlgorithm) { case HashAlgorithms.MD5: haSigner = System.Security.Cryptography.MD5.Create(); break; case HashAlgorithms.SHA1: haSigner = System.Security.Cryptography.SHA1.Create(); break; default: throw(new System.Exception("Currently only MD5 and SHA1 are implemented as hash algorithms!")); } switch (this.SignatureAlgorithm) { case AsymAlgorithms.DSA: acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.DSA(); break; case AsymAlgorithms.RSA_Encrypt_Sign: case AsymAlgorithms.RSA_Sign_Only: acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.RSA(); break; default: throw(new System.Exception("Currently only DSA and RSA are implemented as signature algorithms!")); } byte[] bSignature = new byte[0]; int iCounter = 0; if (this.Version <= SignaturePacketVersionNumbers.v3) { bSignature = new byte[5]; bSignature[iCounter++] = (byte)this.SignatureType; long lTime = (dtTimeCreated.Ticks - new DateTime(1970, 1, 1).Ticks)/10000000; bSignature[iCounter++] = (byte)((lTime >> 24) & 0xFF); bSignature[iCounter++] = (byte)((lTime >> 16) & 0xFF); bSignature[iCounter++] = (byte)((lTime >> 8) & 0xFF); bSignature[iCounter++] = (byte)(lTime & 0xFF); } else { // Add Issuer KeyID Subpacket if it's not there. try { ulong lTestForKeyID = this.KeyID; } catch (Exception) { SignatureSubPacket sspIssuerKeyID = new SignatureSubPacket(); sspIssuerKeyID.Type = SignatureSubPacketTypes.IssuerKeyID; sspIssuerKeyID.KeyID = this.lKeyID; this.AddSubPacket(sspIssuerKeyID, true); } // Add TimeCreated Subpacket if it's not there. try { this.FindSignatureCreationTime(); } catch (Exception) { SignatureSubPacket sspCreationTime = new SignatureSubPacket(); sspCreationTime.Type = SignatureSubPacketTypes.SignatureCreationTime; sspCreationTime.TimeCreated = DateTime.Now; this.AddSubPacket(sspCreationTime, true); } //Hashed Subpackets Length int lHashedSubPacketLength = 0; for (int i=0; i<this.HashedSubPackets.Length; i++) { lHashedSubPacketLength += this.HashedSubPackets[i].Generate().Length; } bSignature = new byte[lHashedSubPacketLength + 12]; bSignature[iCounter++] = 4; // Version bSignature[iCounter++] = (byte)this.SignatureType; bSignature[iCounter++] = (byte)this.SignatureAlgorithm; bSignature[iCounter++] = (byte)this.HashAlgorithm; //Hashed bSignature[iCounter++] = (byte)((lHashedSubPacketLength >> 8) & 0xFF); bSignature[iCounter++] = (byte)(lHashedSubPacketLength & 0xFF); for (int i=0; i<this.HashedSubPackets.Length; i++) { byte[] bSubPacket = this.HashedSubPackets[i].Generate(); Array.Copy(bSubPacket, 0, bSignature, iCounter, bSubPacket.Length); iCounter += bSubPacket.Length; } //Final Trailer of 6 bytes bSignature[iCounter++] = 0x04; bSignature[iCounter++] = 0xFF; bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 24) & 0xFF); bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 16) & 0xFF); bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 8) & 0xFF); bSignature[iCounter++] = (byte)((lHashedSubPacketLength+6) & 0xFF); } byte[] bData = new byte[bSignedData.Length + bSignature.Length]; Array.Copy(bSignedData, bData, bSignedData.Length); Array.Copy(bSignature, 0, bData, bSignedData.Length, bSignature.Length); byte[] bHash = haSigner.ComputeHash(bData); BigInteger biHash = new BigInteger(bHash); //PKCS1 Encode the hash if (this.SignatureAlgorithm != AsymAlgorithms.DSA) { // We encode the MD in this way: // 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) // PAD consists of FF bytes. byte[] bASN = new byte[0]; switch (this.HashAlgorithm) { case HashAlgorithms.MD5: bASN = new byte[] {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; break; case HashAlgorithms.SHA1: bASN = new byte[] {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; break; } int iFrameSize = (skpKey.PublicKey.KeyMaterial[0].bitCount() + 7) / 8; byte[] bFrame = new byte[iFrameSize]; int iASNCounter = 0; bFrame[iASNCounter++] = 0; bFrame[iASNCounter++] = 1; int iFFLength = iFrameSize - bHash.Length - bASN.Length - 3; for (int i=0; i<iFFLength; i++) bFrame[iASNCounter++] = 0xFF; bFrame[iASNCounter++] = 0; Array.Copy(bASN, 0, bFrame, iASNCounter, bASN.Length); iASNCounter += bASN.Length; Array.Copy(bHash, 0, bFrame, iASNCounter, bHash.Length); biHash = new BigInteger(bFrame); } sSignedHash16Bit = (ushort)((bHash[0] << 8) + bHash[1]); biSignature = acSigner.Sign(biHash, skpKey, strPassphrase); this.bIsUpdated = true; }