/** * Parse a secret key from one of the GPG S expression keys. * * @return a secret key object. */ public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] passPhrase) { SXprUtilities.SkipOpenParenthesis(inputStream); string type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (type.Equals("protected-private-key")) { SXprUtilities.SkipOpenParenthesis(inputStream); string curveName; string keyType = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (keyType.Equals("ecc")) { SXprUtilities.SkipOpenParenthesis(inputStream); string curveID = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); curveName = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (curveName.StartsWith("NIST ")) { curveName = curveName.Substring("NIST ".Length); } SXprUtilities.SkipCloseParenthesis(inputStream); } else { throw new PgpException("no curve details found"); } byte[] qVal; SXprUtilities.SkipOpenParenthesis(inputStream); type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (type.Equals("q")) { qVal = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte()); } else { throw new PgpException("no q value found"); } PublicKeyPacket pubPacket = new PublicKeyPacket(PublicKeyAlgorithmTag.ECDsa, DateTime.UtcNow, new ECDsaPublicBcpgKey(ECNamedCurveTable.GetOid(curveName), new BigInteger(1, qVal))); SXprUtilities.SkipCloseParenthesis(inputStream); byte[] dValue = GetDValue(inputStream, passPhrase, curveName); // TODO: check SHA-1 hash. return(new PgpSecretKey(new SecretKeyPacket(pubPacket, SymmetricKeyAlgorithmTag.Null, null, null, new ECSecretBcpgKey(new BigInteger(1, dValue)).GetEncoded()), new PgpPublicKey(pubPacket))); } throw new PgpException("unknown key type found"); }
public void SignKeyBindingSignature(PublicKeyPacket pkpPrimaryKey, SecretKeyPacket skpPrimaryKey, string strPassphrase) { byte[] bSubKey = new byte[pkpSubkey.Body.Length + 3]; bSubKey[0] = 0x99; bSubKey[1] = (byte)((pkpSubkey.Body.Length >> 8) & 0xFF); bSubKey[2] = (byte)(pkpSubkey.Body.Length & 0xFF); Array.Copy(pkpSubkey.Body, 0, bSubKey, 3, pkpSubkey.Body.Length); byte[] bPrimaryKey = new byte[pkpPrimaryKey.Body.Length + 3]; bPrimaryKey[0] = 0x99; bPrimaryKey[1] = (byte)((pkpPrimaryKey.Body.Length >> 8) & 0xFF); bPrimaryKey[2] = (byte)(pkpPrimaryKey.Body.Length & 0xFF); Array.Copy(pkpPrimaryKey.Body, 0, bPrimaryKey, 3, pkpPrimaryKey.Body.Length); byte[] bData = new byte[bPrimaryKey.Length + bSubKey.Length]; Array.Copy(bSubKey, 0, bData, 0, bSubKey.Length); Array.Copy(bPrimaryKey, 0, bData, bSubKey.Length, bPrimaryKey.Length); SignaturePacket spKeyBindingSig = new SignaturePacket(); spKeyBindingSig.Version = SignaturePacketVersionNumbers.v4; spKeyBindingSig.HashAlgorithm = HashAlgorithms.SHA1; spKeyBindingSig.KeyID = pkpPrimaryKey.KeyID; spKeyBindingSig.SignatureType = SignatureTypes.SubkeyBindingSignature; spKeyBindingSig.Sign(bData, skpPrimaryKey, strPassphrase); this.KeyBindingSignature = spKeyBindingSig; }
/// <summary>Copy constructor.</summary> /// <param name="pubKey">The public key to copy.</param> internal PgpPublicKey( PgpPublicKey pubKey) { this.publicPk = pubKey.publicPk; this.keySigs = Platform.CreateArrayList(pubKey.keySigs); this.ids = Platform.CreateArrayList(pubKey.ids); this.idTrusts = Platform.CreateArrayList(pubKey.idTrusts); this.idSigs = Platform.CreateArrayList(pubKey.idSigs.Count); for (int i = 0; i != pubKey.idSigs.Count; i++) { this.idSigs.Add(Platform.CreateArrayList((IList)pubKey.idSigs[i])); } if (pubKey.subSigs != null) { this.subSigs = Platform.CreateArrayList(pubKey.subSigs.Count); for (int i = 0; i != pubKey.subSigs.Count; i++) { this.subSigs.Add(pubKey.subSigs[i]); } } this.fingerprint = pubKey.fingerprint; this.keyId = pubKey.keyId; this.keyStrength = pubKey.keyStrength; }
internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[] rawPassPhrase, bool clearPassPhrase) { SXprUtilities.SkipOpenParenthesis(inputStream); string text = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (text.Equals("protected-private-key")) { SXprUtilities.SkipOpenParenthesis(inputStream); string text2 = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (text2.Equals("ecc")) { SXprUtilities.SkipOpenParenthesis(inputStream); SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); string text3 = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (Platform.StartsWith(text3, "NIST ")) { text3 = text3.Substring("NIST ".get_Length()); } SXprUtilities.SkipCloseParenthesis(inputStream); SXprUtilities.SkipOpenParenthesis(inputStream); text = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (text.Equals("q")) { byte[] bytes = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte()); PublicKeyPacket publicKeyPacket = new PublicKeyPacket(PublicKeyAlgorithmTag.ECDsa, global::System.DateTime.get_UtcNow(), new ECDsaPublicBcpgKey(ECNamedCurveTable.GetOid(text3), new BigInteger(1, bytes))); SXprUtilities.SkipCloseParenthesis(inputStream); byte[] dValue = GetDValue(inputStream, rawPassPhrase, clearPassPhrase, text3); return(new PgpSecretKey(new SecretKeyPacket(publicKeyPacket, SymmetricKeyAlgorithmTag.Null, null, null, new ECSecretBcpgKey(new BigInteger(1, dValue)).GetEncoded()), new PgpPublicKey(publicKeyPacket))); } throw new PgpException("no q value found"); } throw new PgpException("no curve details found"); } throw new PgpException("unknown key type found"); }
public PgpPublicKeyRing( Stream inputStream) { this.keys = Platform.CreateArrayList(); BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream); PacketTag initialTag = bcpgInput.NextPacketTag(); if (initialTag != PacketTag.PublicKey && initialTag != PacketTag.PublicSubkey) { throw new IOException("public key ring doesn't start with public key tag: " + "tag 0x" + ((int)initialTag).ToString("X")); } PublicKeyPacket pubPk = (PublicKeyPacket)bcpgInput.ReadPacket();; TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput); // direct signatures and revocations IList keySigs = ReadSignaturesAndTrust(bcpgInput); IList ids, idTrusts, idSigs; ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs); keys.Add(new PgpPublicKey(pubPk, trustPk, keySigs, ids, idTrusts, idSigs)); // Read subkeys while (bcpgInput.NextPacketTag() == PacketTag.PublicSubkey) { keys.Add(ReadSubkey(bcpgInput)); } }
/// <summary> /// Public key operation. Encrypts biInput with the keydata /// in the given public key packet. /// </summary> /// <param name="biInput">The plaintext that is about to /// be encrypted</param> /// <param name="pkpKey">The public key packet with the key /// material for the encryption</param> /// <returns>The encrypted ciphertext.</returns> /// <remarks>No remarks.</remarks> public override BigInteger[] Encrypt(BigInteger biInput, PublicKeyPacket pkpKey) { EG_Public_Key epkKey = new EG_Public_Key(); epkKey.p = pkpKey.KeyMaterial[0]; epkKey.g = pkpKey.KeyMaterial[1]; epkKey.y = pkpKey.KeyMaterial[2]; BigInteger k = new BigInteger(); //Random number needed for encryption k = BigInteger.genRandom(epkKey.p.bitCount() - 1); while (k > (epkKey.p - 1)) { k = new BigInteger(); k = BigInteger.genRandom(epkKey.p.bitCount() - 1); } BigInteger B = epkKey.g.modPow(k, epkKey.p); BigInteger c = epkKey.y.modPow(k, epkKey.p); c = (biInput * c) % epkKey.p; //BigInteger c = (biInput * epkKey.y.modPow(k, epkKey.p)) % epkKey.p; BigInteger[] biOutput = new BigInteger[2]; biOutput[0] = B; biOutput[1] = c; return(biOutput); }
internal SecretKeyPacket(BcpgInputStream bcpgIn) { if (this is SecretSubkeyPacket) { pubKeyPacket = new PublicSubkeyPacket(bcpgIn); } else { pubKeyPacket = new PublicKeyPacket(bcpgIn); } s2kUsage = bcpgIn.ReadByte(); if (s2kUsage == 255 || s2kUsage == 254) { encAlgorithm = (SymmetricKeyAlgorithmTag)bcpgIn.ReadByte(); s2k = new S2k(bcpgIn); } else { encAlgorithm = (SymmetricKeyAlgorithmTag)s2kUsage; } if ((s2k == null || s2k.Type != 101 || s2k.ProtectionMode != 1) && s2kUsage != 0) { if (encAlgorithm < SymmetricKeyAlgorithmTag.Aes128) { iv = new byte[8]; } else { iv = new byte[16]; } bcpgIn.ReadFully(iv); } secKeyData = bcpgIn.ReadAll(); }
internal PgpPublicKey(PublicKeyPacket publicPk, TrustPacket trustPk, global::System.Collections.IList sigs) { this.publicPk = publicPk; this.trustPk = trustPk; subSigs = sigs; Init(); }
private static ESKSequence CreateESKSequence(ArrayList alKeys, AsymActions aaAction, SymAlgorithms saAlgo, byte[] bSymKey) { IEnumerator ieKeys = alKeys.GetEnumerator(); ESKSequence esksReturn = new ESKSequence(); while (ieKeys.MoveNext()) { TransportablePublicKey tpkKey = (TransportablePublicKey)ieKeys.Current; PublicKeyPacket pkpKey = tpkKey.FindKey(aaAction); if (pkpKey == null) { throw new Exception("Could not find subkey fitting to the selected action. Concerned Key: " + tpkKey.PrimaryUserID); } AsymSessionKeyPacket skpKey = new AsymSessionKeyPacket(); skpKey.KeyID = pkpKey.KeyID; skpKey.PublicAlgorithm = pkpKey.Algorithm; skpKey.SymmetricAlgorithm = saAlgo; skpKey.SessionKey = bSymKey; skpKey.EncryptSessionKey(pkpKey); esksReturn.AddAsymSessionKey(skpKey); } return(esksReturn); }
public static byte[] CreateKey(PublicKeyPacket pubKeyData, ECPoint s) { byte[] parameters = CreateUserKeyingMaterial(pubKeyData); ECDHPublicBcpgKey eCDHPublicBcpgKey = (ECDHPublicBcpgKey)pubKeyData.Key; return(Kdf(eCDHPublicBcpgKey.HashAlgorithm, s, GetKeyLength(eCDHPublicBcpgKey.SymmetricKeyAlgorithm), parameters)); }
/// <summary> /// Finds a subkey (or the primary key) with the given keyid /// and returns it. Returns null if the the fitting key has /// not been found. /// </summary> /// <remarks>If the public key has been revoked, it is ignored /// and NOT found by this function!!!</remarks> /// <param name="lKeyID">The keyid to be sought in the transportable /// public key.</param> /// <returns>The subkey (or the primary key) with the given keyid. /// Null if the the fitting key has not been found.</returns> public PublicKeyPacket FindKey(ulong lKeyID) { if (pkpPrimaryKey.KeyID == lKeyID) { return(pkpPrimaryKey); } IEnumerator ieSubkeys = alSubkeys.GetEnumerator(); while (ieSubkeys.MoveNext()) { CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current; // The subkey has been revoced if (cpsKey.RevocationSignature != null) { continue; } PublicKeyPacket pkpKey = cpsKey.Subkey; if (pkpKey.KeyID == lKeyID) { return(pkpKey); } } return(null); }
internal PgpPublicKey(PublicKeyPacket publicPk, global::System.Collections.IList ids, global::System.Collections.IList idSigs) { this.publicPk = publicPk; this.ids = ids; this.idSigs = idSigs; Init(); }
private ESKSequence CreateESKSequence(TransportablePublicKey[] tpkKeys, AsymActions aaAction, SymAlgorithms saAlgo, byte[] bSymKey) { ESKSequence esksReturn = new ESKSequence(); for (int i = 0; i < tpkKeys.Length; i++) { TransportablePublicKey tpkKey = tpkKeys[i]; PublicKeyPacket pkpKey = tpkKey.FindKey(aaAction); if (pkpKey == null) { throw new Exception("Could not find subkey fitting to the selected action. Concerned Key: " + tpkKey.PrimaryUserID); } AsymSessionKeyPacket skpKey = new AsymSessionKeyPacket(); skpKey.KeyID = pkpKey.KeyID; skpKey.PublicAlgorithm = pkpKey.Algorithm; skpKey.SymmetricAlgorithm = saAlgo; skpKey.SessionKey = bSymKey; skpKey.EncryptSessionKey(pkpKey); esksReturn.AddAsymSessionKey(skpKey); } return(esksReturn); }
public static IAsymmetricPublicKey ConvertPublic(PgpPublicKey publicKey) { PublicKeyPacket publicPk = publicKey.PublicKeyPacket; switch (publicKey.Algorithm) { case PublicKeyAlgorithmTag.RsaEncrypt: case PublicKeyAlgorithmTag.RsaGeneral: case PublicKeyAlgorithmTag.RsaSign: RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey)publicPk.Key; return(new AsymmetricRsaPublicKey(FipsRsa.Alg, rsaK.Modulus, rsaK.PublicExponent)); case PublicKeyAlgorithmTag.Dsa: DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey)publicPk.Key; return(new AsymmetricDsaPublicKey(FipsDsa.Alg, new DsaDomainParameters(dsaK.P, dsaK.Q, dsaK.G), dsaK.Y)); case PublicKeyAlgorithmTag.ElGamalEncrypt: case PublicKeyAlgorithmTag.ElGamalGeneral: ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey)publicPk.Key; return(new AsymmetricDHPublicKey(FipsDsa.Alg, new DHDomainParameters(elK.P, elK.G), elK.Y)); default: throw new PgpException("unknown public key algorithm encountered"); } }
internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput) { PublicKeyPacket publicPk = (PublicKeyPacket)bcpgInput.ReadPacket(); TrustPacket trustPk = PgpKeyRing.ReadOptionalTrustPacket(bcpgInput); IList sigs = PgpKeyRing.ReadSignaturesAndTrust(bcpgInput); return(new PgpPublicKey(publicPk, trustPk, sigs)); }
public static byte[] CreateKey(PublicKeyPacket pubKeyData, ECPoint s) { byte[] userKeyingMaterial = CreateUserKeyingMaterial(pubKeyData); ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)pubKeyData.Key; return Kdf(ecKey.HashAlgorithm, s, GetKeyLength(ecKey.SymmetricKeyAlgorithm), userKeyingMaterial); }
internal PgpPublicKey(PgpPublicKey key, TrustPacket trust, global::System.Collections.IList subSigs) { publicPk = key.publicPk; trustPk = trust; this.subSigs = subSigs; fingerprint = key.fingerprint; keyId = key.keyId; keyStrength = key.keyStrength; }
public SecretSubkeyPacket( PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, byte[] iv, byte[] secKeyData) : base(pubKeyPacket, encAlgorithm, s2k, iv, secKeyData) { }
/// <summary> /// Create a PgpPrivateKey from a keyID, the associated public data packet, and a regular private key. /// </summary> /// <param name="keyID">ID of the corresponding public key.</param> /// <param name="publicKeyPacket">the public key data packet to be associated with this private key.</param> /// <param name="privateKey">the private key packet to be associated with this private key.</param> public PgpPrivateKey( long keyID, PublicKeyPacket publicKeyPacket, IBcpgKey privateKey) { this.keyID = keyID; this.publicKeyPacket = publicKeyPacket; this.privateKey = privateKey; }
public SecretKeyPacket(PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, int s2kUsage, S2k s2k, byte[] iv, byte[] secKeyData) { this.pubKeyPacket = pubKeyPacket; this.encAlgorithm = encAlgorithm; this.s2kUsage = s2kUsage; this.s2k = s2k; this.iv = Arrays.Clone(iv); this.secKeyData = secKeyData; }
public static PgpKeyPair Convert(PublicKeyAlgorithmTag algorithmTag, AsymmetricKeyPair <AsymmetricRsaPublicKey, AsymmetricRsaPrivateKey> kp, DateTime date) { PublicKeyPacket pubPacket = new PublicKeyPacket(algorithmTag, date, new RsaPublicBcpgKey(kp.PublicKey.Modulus, kp.PublicKey.PublicExponent)); PgpPublicKey pubKey = new PgpPublicKey(pubPacket, new PgpKeyFingerprintCalculator()); PgpPrivateKey privKey = new PgpPrivateKey(pubKey.KeyId, pubPacket, new RsaSecretBcpgKey(kp.PrivateKey.PrivateExponent, kp.PrivateKey.P, kp.PrivateKey.Q)); return(new PgpKeyPair(pubKey, privKey)); }
internal PgpPublicKey(PublicKeyPacket publicPk, TrustPacket trustPk, global::System.Collections.IList keySigs, global::System.Collections.IList ids, global::System.Collections.IList idTrusts, global::System.Collections.IList idSigs) { this.publicPk = publicPk; this.trustPk = trustPk; this.keySigs = keySigs; this.ids = ids; this.idTrusts = idTrusts; this.idSigs = idSigs; Init(); }
internal PgpPublicKey( PublicKeyPacket publicPk, IList ids, IList idSigs) { this.publicPk = publicPk; this.ids = ids; this.idSigs = idSigs; Init(); }
public PgpPrivateKey(long keyID, PublicKeyPacket publicKeyPacket, AsymmetricKeyParameter privateKey) { if (!privateKey.IsPrivate) { throw new ArgumentException("Expected a private key", "privateKey"); } this.keyID = keyID; this.publicKeyPacket = publicKeyPacket; this.privateKey = privateKey; }
internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput) { PublicKeyPacket pk = (PublicKeyPacket)bcpgInput.ReadPacket(); TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput); // PGP 8 actually leaves out the signature. IList sigList = ReadSignaturesAndTrust(bcpgInput); return(new PgpPublicKey(pk, kTrust, sigList)); }
/** * Extract a PgpPrivate key from the SecretKey's encrypted contents. * * @param decryptorFactory factory to use to generate a decryptor for the passed in secretKey. * @return PgpPrivateKey the unencrypted private key. * @throws PgpException on failure. */ public PgpPrivateKey ExtractPrivateKey( IPbeSecretKeyDecryptorProvider decryptorProvider) { if (IsPrivateKeyEmpty) { return(null); } PublicKeyPacket pubPk = secret.PublicKeyPacket; try { byte[] data = extractKeyData(decryptorProvider); BcpgInputStream input = BcpgInputStream.Wrap(new MemoryInputStream(data)); switch (pubPk.Algorithm) { case PublicKeyAlgorithmTag.RsaEncrypt: case PublicKeyAlgorithmTag.RsaGeneral: case PublicKeyAlgorithmTag.RsaSign: RsaSecretBcpgKey rsaPriv = new RsaSecretBcpgKey(input); return(new PgpPrivateKey(this.KeyId, pubPk, rsaPriv)); case PublicKeyAlgorithmTag.Dsa: DsaSecretBcpgKey dsaPriv = new DsaSecretBcpgKey(input); return(new PgpPrivateKey(this.KeyId, pubPk, dsaPriv)); case PublicKeyAlgorithmTag.ElGamalEncrypt: case PublicKeyAlgorithmTag.ElGamalGeneral: ElGamalSecretBcpgKey elPriv = new ElGamalSecretBcpgKey(input); return(new PgpPrivateKey(this.KeyId, pubPk, elPriv)); case PublicKeyAlgorithmTag.ECDH: case PublicKeyAlgorithmTag.ECDsa: ECSecretBcpgKey ecPriv = new ECSecretBcpgKey(input); return(new PgpPrivateKey(this.KeyId, pubPk, ecPriv)); default: throw new PgpException("unknown public key algorithm encountered"); } } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception constructing key", e); } }
internal PgpPublicKey( PublicKeyPacket publicPk, IList ids, IList <List <PgpSignature> > idSigs, IKeyFingerPrintCalculator fingerPrintCalculator) { this.publicPk = publicPk; this.ids = ids; this.idSigs = idSigs; Init(fingerPrintCalculator); }
public byte[] CalculateFingerprint(PublicKeyPacket publicPk) { IBcpgKey key = publicPk.Key; if (publicPk.Version <= 3) { RsaPublicBcpgKey rK = (RsaPublicBcpgKey)key; try { // TODO: MD5 needs to go in the main API... MD5Digest digest = new MD5Digest(); byte[] bytes = new MPInteger(rK.Modulus).GetEncoded(); digest.BlockUpdate(bytes, 2, bytes.Length - 2); bytes = new MPInteger(rK.PublicExponent).GetEncoded(); digest.BlockUpdate(bytes, 2, bytes.Length - 2); byte[] digBuf = new byte[digest.GetDigestSize()]; digest.DoFinal(digBuf, 0); return(digBuf); } catch (IOException e) { throw new PgpException("can't encode key components: " + e.Message, e); } } else { try { byte[] kBytes = publicPk.GetEncodedContents(); IStreamCalculator <IBlockResult> hashCalc = CryptoServicesRegistrar.CreateService(FipsShs.Sha1).CreateCalculator(); Stream hStream = hashCalc.Stream; hStream.WriteByte((byte)0x99); hStream.WriteByte((byte)(kBytes.Length >> 8)); hStream.WriteByte((byte)kBytes.Length); hStream.Write(kBytes, 0, kBytes.Length); hStream.Close(); return(hashCalc.GetResult().Collect()); } catch (IOException e) { throw new PgpException("can't encode key components: " + e.Message, e); } } }
public PgpPrivateKey(long keyID, PublicKeyPacket publicKeyPacket, AsymmetricKeyParameter privateKey) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!privateKey.IsPrivate) { throw new ArgumentException("Expected a private key", "privateKey"); } this.keyID = keyID; this.publicKeyPacket = publicKeyPacket; this.privateKey = privateKey; }
/// <summary>Constructor for a sub-key.</summary> internal PgpPublicKey( PublicKeyPacket publicPk, TrustPacket trustPk, IList sigs) { this.publicPk = publicPk; this.trustPk = trustPk; this.subSigs = sigs; Init(); }
/// <summary>Constructor for a sub-key.</summary> internal PgpPublicKey( PublicKeyPacket publicPk, TrustPacket trustPk, IList <PgpSignature> sigs, IKeyFingerPrintCalculator fingerPrintCalculator) { this.publicPk = publicPk; this.trustPk = trustPk; this.subSigs = sigs; Init(fingerPrintCalculator); }
/// <summary> /// Create a PgpPrivateKey from a keyID, the associated public data packet, and a regular private key. /// </summary> /// <param name="keyID">ID of the corresponding public key.</param> /// <param name="publicKeyPacket">the public key data packet to be associated with this private key.</param> /// <param name="privateKey">the private key data packet to be associated with this private key.</param> public PgpPrivateKey( long keyID, PublicKeyPacket publicKeyPacket, AsymmetricKeyParameter privateKey) { if (!privateKey.IsPrivate) throw new ArgumentException("Expected a private key", "privateKey"); this.keyID = keyID; this.publicKeyPacket = publicKeyPacket; this.privateKey = privateKey; }
public static string GetAgreementAlgorithm(PublicKeyPacket pubKeyData) { ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)pubKeyData.Key; switch (ecKey.HashAlgorithm) { case HashAlgorithmTag.Sha256: return "ECCDHwithSHA256CKDF"; case HashAlgorithmTag.Sha384: return "ECCDHwithSHA384CKDF"; case HashAlgorithmTag.Sha512: return "ECCDHwithSHA512CKDF"; default: throw new ArgumentException("Unknown hash algorithm specified: " + ecKey.HashAlgorithm); } }
/// <summary> /// Create a PgpPublicKey from the passed in JCA one. /// <p> /// Note: the time passed in affects the value of the key's keyId, so you probably only want /// to do this once for a JCA key, or make sure you keep track of the time you used.</p> /// </summary> public PgpPublicKey( PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, DateTime time) { if (pubKey.IsPrivate) throw new ArgumentException("Expected a public key", "pubKey"); IBcpgKey bcpgKey; if (pubKey is RsaKeyParameters) { RsaKeyParameters rK = (RsaKeyParameters) pubKey; bcpgKey = new RsaPublicBcpgKey(rK.Modulus, rK.Exponent); } else if (pubKey is DsaPublicKeyParameters) { DsaPublicKeyParameters dK = (DsaPublicKeyParameters) pubKey; DsaParameters dP = dK.Parameters; bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y); } else if (pubKey is ElGamalPublicKeyParameters) { ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey; ElGamalParameters eS = eK.Parameters; bcpgKey = new ElGamalPublicBcpgKey(eS.P, eS.G, eK.Y); } else { throw new PgpException("unknown key class"); } this.publicPk = new PublicKeyPacket(algorithm, time, bcpgKey); this.ids = new ArrayList(); this.idSigs = new ArrayList(); try { Init(); } catch (IOException e) { throw new PgpException("exception calculating keyId", e); } }
// RFC 6637 - Section 8 // curve_OID_len = (byte)len(curve_OID); // Param = curve_OID_len || curve_OID || public_key_alg_ID || 03 // || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || "Anonymous // Sender " || recipient_fingerprint; // Z_len = the key size for the KEK_alg_ID used with AESKeyWrap // Compute Z = KDF( S, Z_len, Param ); public static byte[] CreateUserKeyingMaterial(PublicKeyPacket pubKeyData) { MemoryStream pOut = new MemoryStream(); ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)pubKeyData.Key; byte[] encOid = ecKey.CurveOid.GetEncoded(); pOut.Write(encOid, 1, encOid.Length - 1); pOut.WriteByte((byte)pubKeyData.Algorithm); pOut.WriteByte(0x03); pOut.WriteByte(0x01); pOut.WriteByte((byte)ecKey.HashAlgorithm); pOut.WriteByte((byte)ecKey.SymmetricKeyAlgorithm); pOut.Write(ANONYMOUS_SENDER, 0, ANONYMOUS_SENDER.Length); byte[] fingerprint = PgpPublicKey.CalculateFingerprint(pubKeyData); pOut.Write(fingerprint, 0, fingerprint.Length); return pOut.ToArray(); }
public static byte[] CalculateFingerprint(PublicKeyPacket publicPk) { IBcpgKey key = publicPk.Key; IDigest digest; if (publicPk.Version <= 3) { RsaPublicBcpgKey rK = (RsaPublicBcpgKey)key; try { digest = DigestUtilities.GetDigest("MD5"); UpdateDigest(digest, rK.Modulus); UpdateDigest(digest, rK.PublicExponent); } catch (Exception e) { throw new PgpException("can't encode key components: " + e.Message, e); } } else { try { byte[] kBytes = publicPk.GetEncodedContents(); digest = DigestUtilities.GetDigest("SHA1"); digest.Update(0x99); digest.Update((byte)(kBytes.Length >> 8)); digest.Update((byte)kBytes.Length); digest.BlockUpdate(kBytes, 0, kBytes.Length); } catch (Exception e) { throw new PgpException("can't encode key components: " + e.Message, e); } } return DigestUtilities.DoFinal(digest); }
public void SignKeyBindingSignature(PublicKeyPacket pkpPrimaryKey, SecretKeyPacket skpPrimaryKey, string strPassphrase, DateTime expirationTime, bool revocable) { byte[] bSubKey = new byte[pkpSubkey.Body.Length + 3]; bSubKey[0] = 0x99; bSubKey[1] = (byte)((pkpSubkey.Body.Length >> 8) & 0xFF); bSubKey[2] = (byte)(pkpSubkey.Body.Length & 0xFF); Array.Copy(pkpSubkey.Body, 0, bSubKey, 3, pkpSubkey.Body.Length); byte[] bPrimaryKey = new byte[pkpPrimaryKey.Body.Length + 3]; bPrimaryKey[0] = 0x99; bPrimaryKey[1] = (byte)((pkpPrimaryKey.Body.Length >> 8) & 0xFF); bPrimaryKey[2] = (byte)(pkpPrimaryKey.Body.Length & 0xFF); Array.Copy(pkpPrimaryKey.Body, 0, bPrimaryKey, 3, pkpPrimaryKey.Body.Length); byte[] bData = new byte[bPrimaryKey.Length + bSubKey.Length]; Array.Copy(bPrimaryKey, 0, bData, 0, bPrimaryKey.Length); Array.Copy(bSubKey, 0, bData, bPrimaryKey.Length, bSubKey.Length); SignaturePacket spKeyBindingSig = new SignaturePacket(); spKeyBindingSig.Version = SignaturePacketVersionNumbers.v4; spKeyBindingSig.HashAlgorithm = HashAlgorithms.SHA1; spKeyBindingSig.KeyID = pkpPrimaryKey.KeyID; spKeyBindingSig.SignatureType = SignatureTypes.SubkeyBindingSignature; if(expirationTime.Ticks != 0) { SignatureSubPacket sspExpiration = new SignatureSubPacket(); sspExpiration.Type = SignatureSubPacketTypes.KeyExpirationTime; sspExpiration.KeyExpirationTime = new DateTime(expirationTime.Ticks + (new DateTime(1970,1,2)).Ticks - pkpPrimaryKey.TimeCreated.Ticks); spKeyBindingSig.AddSubPacket(sspExpiration, true); } if(!revocable) { SignatureSubPacket sspRevocable = new SignatureSubPacket(); sspRevocable.Type = SignatureSubPacketTypes.Revocable; sspRevocable.Revocable = revocable; spKeyBindingSig.AddSubPacket(sspRevocable, true); } spKeyBindingSig.Sign(bData, skpPrimaryKey, strPassphrase); this.KeyBindingSignature = spKeyBindingSig; }
internal PgpPublicKey( PublicKeyPacket publicPk, IList ids, IList idSigs) { this.publicPk = publicPk; this.ids = ids; this.idSigs = idSigs; Init(); }
internal PgpPublicKey( PublicKeyPacket publicPk, TrustPacket trustPk, IList keySigs, IList ids, IList idTrusts, IList idSigs) { this.publicPk = publicPk; this.trustPk = trustPk; this.keySigs = keySigs; this.ids = ids; this.idTrusts = idTrusts; this.idSigs = idSigs; Init(); }
/// <summary>Copy constructor.</summary> /// <param name="pubKey">The public key to copy.</param> internal PgpPublicKey( PgpPublicKey pubKey) { this.publicPk = pubKey.publicPk; this.keySigs = Platform.CreateArrayList(pubKey.keySigs); this.ids = Platform.CreateArrayList(pubKey.ids); this.idTrusts = Platform.CreateArrayList(pubKey.idTrusts); this.idSigs = Platform.CreateArrayList(pubKey.idSigs.Count); for (int i = 0; i != pubKey.idSigs.Count; i++) { this.idSigs.Add(Platform.CreateArrayList((IList)pubKey.idSigs[i])); } if (pubKey.subSigs != null) { this.subSigs = Platform.CreateArrayList(pubKey.subSigs.Count); for (int i = 0; i != pubKey.subSigs.Count; i++) { this.subSigs.Add(pubKey.subSigs[i]); } } this.fingerprint = pubKey.fingerprint; this.keyId = pubKey.keyId; this.keyStrength = pubKey.keyStrength; }
internal PgpPublicKey( PgpPublicKey key, TrustPacket trust, IList subSigs) { this.publicPk = key.publicPk; this.trustPk = trust; this.subSigs = subSigs; this.fingerprint = key.fingerprint; this.keyId = key.keyId; this.keyStrength = key.keyStrength; }
/// <summary>Constructor for a sub-key.</summary> internal PgpPublicKey( PublicKeyPacket publicPk, TrustPacket trustPk, IList sigs) { this.publicPk = publicPk; this.trustPk = trustPk; this.subSigs = sigs; Init(); }
/// <summary> /// Parse a secret key from one of the GPG S expression keys. /// </summary> internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[] rawPassPhrase, bool clearPassPhrase) { SXprUtilities.SkipOpenParenthesis(inputStream); string type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (type.Equals("protected-private-key")) { SXprUtilities.SkipOpenParenthesis(inputStream); string curveName; string keyType = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (keyType.Equals("ecc")) { SXprUtilities.SkipOpenParenthesis(inputStream); string curveID = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); curveName = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (Platform.StartsWith(curveName, "NIST ")) { curveName = curveName.Substring("NIST ".Length); } SXprUtilities.SkipCloseParenthesis(inputStream); } else { throw new PgpException("no curve details found"); } byte[] qVal; SXprUtilities.SkipOpenParenthesis(inputStream); type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte()); if (type.Equals("q")) { qVal = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte()); } else { throw new PgpException("no q value found"); } PublicKeyPacket pubPacket = new PublicKeyPacket(PublicKeyAlgorithmTag.ECDsa, DateTime.UtcNow, new ECDsaPublicBcpgKey(ECNamedCurveTable.GetOid(curveName), new BigInteger(1, qVal))); SXprUtilities.SkipCloseParenthesis(inputStream); byte[] dValue = GetDValue(inputStream, rawPassPhrase, clearPassPhrase, curveName); // TODO: check SHA-1 hash. return new PgpSecretKey(new SecretKeyPacket(pubPacket, SymmetricKeyAlgorithmTag.Null, null, null, new ECSecretBcpgKey(new BigInteger(1, dValue)).GetEncoded()), new PgpPublicKey(pubPacket)); } throw new PgpException("unknown key type found"); }
public void VerifyKeyBindingSignature(PublicKeyPacket pkpPrimaryKey) { if (this.KeyBindingSignature.Version == SignaturePacketVersionNumbers.v4) { byte[] bSubKey = new byte[pkpSubkey.Body.Length + 3]; bSubKey[0] = 0x99; bSubKey[1] = (byte)((pkpSubkey.Body.Length >> 8) & 0xFF); bSubKey[2] = (byte)(pkpSubkey.Body.Length & 0xFF); Array.Copy(pkpSubkey.Body, 0, bSubKey, 3, pkpSubkey.Body.Length); byte[] bPrimaryKey = new byte[pkpPrimaryKey.Body.Length + 3]; bPrimaryKey[0] = 0x99; bPrimaryKey[1] = (byte)((pkpPrimaryKey.Body.Length >> 8) & 0xFF); bPrimaryKey[2] = (byte)(pkpPrimaryKey.Body.Length & 0xFF); Array.Copy(pkpPrimaryKey.Body, 0, bPrimaryKey, 3, pkpPrimaryKey.Body.Length); byte[] bData = new byte[bPrimaryKey.Length + bSubKey.Length]; Array.Copy(bPrimaryKey, 0, bData, 0, bPrimaryKey.Length); Array.Copy(bSubKey, 0, bData, bPrimaryKey.Length, bSubKey.Length); this.KeyBindingSignature.Verify(bData, pkpPrimaryKey); } }
/// <summary> /// Finds a subkey (or the primary key) that fits to the given /// requirements (meaning it must be supposed to be used for /// the given action, which can be either signing or encryption). /// If more than just one keys fullfill the requirements, the one /// with the newer creationdate is used. /// </summary> /// <remarks>No remarks</remarks> /// <param name="aaAction">The action (signing or encrypting) for /// which the key should be used</param> /// <returns>Returns a public key packet fullfilling the given /// requirements (the action) or null, if it did not find such /// a key.</returns> public PublicKeyPacket FindKey(AsymActions aaAction) { DateTime dtCandidateTime = DateTime.Now; PublicKeyPacket pkpCandidate = new PublicKeyPacket(); bool bFound = false; // First check the primary Key if (aaAction == AsymActions.Encrypt) { if (pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign || pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGamal_Encrypt_Only || pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Only || pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) { dtCandidateTime = pkpPrimaryKey.TimeCreated; bFound = true; pkpCandidate = pkpPrimaryKey; } } else if (aaAction == AsymActions.Sign) { if (pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign || pkpPrimaryKey.Algorithm == AsymAlgorithms.DSA || pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Sign_Only || pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) { dtCandidateTime = pkpPrimaryKey.TimeCreated; bFound = true; pkpCandidate = pkpPrimaryKey; } } // Now check the subkeys IEnumerator ieSubkeys = alSubkeys.GetEnumerator(); while (ieSubkeys.MoveNext()) { CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current; // The subkey has been revoced if (cpsKey.RevocationSignature != null) continue; PublicKeyPacket pkpKey = cpsKey.Subkey; if (aaAction == AsymActions.Encrypt) { if (pkpKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign || pkpKey.Algorithm == AsymAlgorithms.ElGamal_Encrypt_Only || pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Only || pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) { if ((bFound && dtCandidateTime < pkpKey.TimeCreated) || (!bFound)) { dtCandidateTime = pkpKey.TimeCreated; bFound = true; pkpCandidate = pkpKey; } } } else if (aaAction == AsymActions.Sign) { if (pkpKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign || pkpKey.Algorithm == AsymAlgorithms.DSA || pkpKey.Algorithm == AsymAlgorithms.RSA_Sign_Only || pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) { if ((bFound && dtCandidateTime < pkpKey.TimeCreated) || (!bFound)) { dtCandidateTime = pkpKey.TimeCreated; bFound = true; pkpCandidate = pkpKey; } } } } if (bFound) return pkpCandidate; return null; }
public PgpPublicKey(PublicKeyPacket publicPk) : this(publicPk, Platform.CreateArrayList(), Platform.CreateArrayList()) { }
/// <summary> /// Validates all certificates belonging the the given public key packet /// and the current certifications. /// </summary> /// <remarks> /// So far only works with v4 signatures! /// </remarks> /// <param name="pkpKey">The public key packet to which the userid /// belongs.</param> /// <param name="pkrRing">A keyring containing all public keys known to /// the system. This is neccessary in order to verify the signatures. /// </param> public void Validate(PublicKeyPacket pkpKey, PublicKeyRing pkrRing) { IEnumerator ieCertificates = Certificates.GetEnumerator(); this.validitystatus = ValidityStatus.Valid; while (ieCertificates.MoveNext()) { if (ieCertificates.Current is SignaturePacket) { SignaturePacket spCert = (SignaturePacket)ieCertificates.Current; TransportablePublicKey tkpSigningKey = pkrRing.Find(spCert.KeyID, true); if (tkpSigningKey == null) { this.validitystatus = ValidityStatus.ValidationKeyUnavailable; continue; } PublicKeyPacket pkpSigningKey = tkpSigningKey.PrimaryKey; if (spCert.Version == SignaturePacketVersionNumbers.v4) { byte[] bKey = new byte[pkpKey.Body.Length + 3]; bKey[0] = 0x99; bKey[1] = (byte)((pkpKey.Body.Length >> 8) & 0xFF); bKey[2] = (byte)(pkpKey.Body.Length & 0xFF); Array.Copy(pkpKey.Body, 0, bKey, 3, pkpKey.Body.Length); byte[] bUserID = new byte[UserID.Body.Length + 5]; bUserID[0] = 0xb4; bUserID[1] = (byte)((UserID.Body.Length >> 24) & 0xFF); bUserID[2] = (byte)((UserID.Body.Length >> 16) & 0xFF); bUserID[3] = (byte)((UserID.Body.Length >> 8) & 0xFF); bUserID[4] = (byte)(UserID.Body.Length & 0xFF); Array.Copy(UserID.Body, 0, bUserID, 5, UserID.Body.Length); byte[] bData = new byte[bUserID.Length + bKey.Length]; Array.Copy(bKey, 0, bData, 0, bKey.Length); Array.Copy(bUserID, 0, bData, bKey.Length, bUserID.Length); spCert.Verify(bData, pkpSigningKey); if(spCert.SignatureStatus == SignatureStatusTypes.Invalid) { this.validitystatus = ValidityStatus.Invalid; continue; } else if(spCert.SignatureStatus == SignatureStatusTypes.Signing_Key_Not_Available) { this.validitystatus = ValidityStatus.ValidationKeyUnavailable; continue; } else if(spCert.SignatureStatus == SignatureStatusTypes.Not_Verified) { this.validitystatus = ValidityStatus.NotYetValidated; continue; } } else { //TODO: Add code for v3 Signature verification } } } }
/// <summary> /// Creates a new Certification for the UserID. /// </summary> /// <param name="spSignature">A signaturepacket that has been /// prepared for being signed. Things like signature subpackets /// MUST already be in place. Only the signature type is /// automatically set to UserIDCertification.</param> /// <param name="skpKey">A secret key that is used to signed the /// certification.</param> /// <param name="strPassphrase">The passphrase that fits to the /// given secret key packet.</param> /// <param name="pkpKey">The public key to which the userid that /// is to be signed belongs.</param> public void Sign(SignaturePacket spSignature, SecretKeyPacket skpKey, string strPassphrase, PublicKeyPacket pkpKey) { if (spSignature.Version == SignaturePacketVersionNumbers.v4) { byte[] bKey = new byte[pkpKey.Body.Length + 3]; bKey[0] = 0x99; bKey[1] = (byte)((pkpKey.Body.Length >> 8) & 0xFF); bKey[2] = (byte)(pkpKey.Body.Length & 0xFF); Array.Copy(pkpKey.Body, 0, bKey, 3, pkpKey.Body.Length); byte[] bUserID = new byte[UserID.Body.Length + 5]; bUserID[0] = 0xb4; bUserID[1] = (byte)((UserID.Body.Length >> 24) & 0xFF); bUserID[2] = (byte)((UserID.Body.Length >> 16) & 0xFF); bUserID[3] = (byte)((UserID.Body.Length >> 8) & 0xFF); bUserID[4] = (byte)(UserID.Body.Length & 0xFF); Array.Copy(UserID.Body, 0, bUserID, 5, UserID.Body.Length); byte[] bData = new byte[bUserID.Length + bKey.Length]; Array.Copy(bKey, 0, bData, 0, bKey.Length); Array.Copy(bUserID, 0, bData, bKey.Length, bUserID.Length); spSignature.SignatureType = SignatureTypes.UserIDSignature; spSignature.Sign(bData, skpKey, strPassphrase); this.alCertificates.Add(spSignature); } else { throw new System.NotImplementedException("Only v4 signatures are supported so far!"); } }