public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random) { byte[] keyBytes = contentEncryptionKey.GetKey(); string rfc3211WrapperName = Helper.GetRfc3211WrapperName(keyEncryptionKeyOID); IWrapper keyWrapper = Helper.CreateWrapper(rfc3211WrapperName); // Note: In Java build, the IV is automatically generated in JCE layer int ivLength = rfc3211WrapperName.StartsWith("DESEDE") ? 8 : 16; byte[] iv = new byte[ivLength]; random.NextBytes(iv); ICipherParameters parameters = new ParametersWithIV(keyEncryptionKey, iv); keyWrapper.Init(true, new ParametersWithRandom(parameters, random)); Asn1OctetString encryptedKey = new DerOctetString( keyWrapper.Wrap(keyBytes, 0, keyBytes.Length)); DerSequence seq = new DerSequence( new DerObjectIdentifier(keyEncryptionKeyOID), new DerOctetString(iv)); AlgorithmIdentifier keyEncryptionAlgorithm = new AlgorithmIdentifier( PkcsObjectIdentifiers.IdAlgPwriKek, seq); return new RecipientInfo(new PasswordRecipientInfo( keyDerivationAlgorithm, keyEncryptionAlgorithm, encryptedKey)); }
public void Save(Stream stream, char[] password, SecureRandom random) { if (stream == null) { throw new ArgumentNullException("stream"); } if (password == null) { throw new ArgumentNullException("password"); } if (random == null) { throw new ArgumentNullException("random"); } // // handle the key // var keyS = new Asn1EncodableVector(); foreach (string name in _keys.Keys) { var kSalt = new byte[SaltSize]; random.NextBytes(kSalt); var privKey = (AsymmetricKeyEntry) _keys[name]; EncryptedPrivateKeyInfo kInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(_keyAlgorithm, password, kSalt, MinIterations, privKey.Key); var kName = new Asn1EncodableVector(); foreach (string oid in privKey.BagAttributeKeys) { Asn1Encodable entry = privKey[oid]; // NB: Ignore any existing FriendlyName if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id)) { continue; } kName.Add(new DerSequence(new DerObjectIdentifier(oid), new DerSet(entry))); } // // make sure we are using the local alias on store // // NB: We always set the FriendlyName based on 'name' //if (privKey[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null) { kName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(name)))); } // // make sure we have a local key-id // if (privKey[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null) { X509CertificateEntry ct = GetCertificate(name); AsymmetricKeyParameter pubKey = ct.Certificate.GetPublicKey(); SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey); kName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(subjectKeyID))); } var kBag = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, kInfo.ToAsn1Object(), new DerSet(kName)); keyS.Add(kBag); } byte[] derEncodedBytes = new DerSequence(keyS).GetDerEncoded(); var keyString = new BerOctetString(derEncodedBytes); // // certificate processing // var cSalt = new byte[SaltSize]; random.NextBytes(cSalt); var certSeq = new Asn1EncodableVector(); var cParams = new Pkcs12PbeParams(cSalt, MinIterations); var cAlgId = new AlgorithmIdentifier(_certAlgorithm, cParams.ToAsn1Object()); ISet doneCerts = new HashSet(); foreach (string name in _keys.Keys) { X509CertificateEntry certEntry = GetCertificate(name); var cBag = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(certEntry.Certificate.GetEncoded())); var fName = new Asn1EncodableVector(); foreach (string oid in certEntry.BagAttributeKeys) { Asn1Encodable entry = certEntry[oid]; // NB: Ignore any existing FriendlyName if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id)) { continue; } fName.Add(new DerSequence(new DerObjectIdentifier(oid), new DerSet(entry))); } // // make sure we are using the local alias on store // // NB: We always set the FriendlyName based on 'name' //if (certEntry[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null) { fName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(name)))); } // // make sure we have a local key-id // if (certEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null) { AsymmetricKeyParameter pubKey = certEntry.Certificate.GetPublicKey(); SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey); fName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(subjectKeyID))); } var sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)); certSeq.Add(sBag); doneCerts.Add(certEntry.Certificate); } foreach (string certId in _certs.Keys) { var cert = (X509CertificateEntry) _certs[certId]; if (_keys[certId] != null) { continue; } var cBag = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(cert.Certificate.GetEncoded())); var fName = new Asn1EncodableVector(); foreach (string oid in cert.BagAttributeKeys) { // a certificate not immediately linked to a key doesn't require // a localKeyID and will confuse some PKCS12 implementations. // // If we find one, we'll prune it out. if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id)) { continue; } Asn1Encodable entry = cert[oid]; // NB: Ignore any existing FriendlyName if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id)) { continue; } fName.Add(new DerSequence(new DerObjectIdentifier(oid), new DerSet(entry))); } // // make sure we are using the local alias on store // // NB: We always set the FriendlyName based on 'certId' //if (cert[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null) { fName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(certId)))); } var sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)); certSeq.Add(sBag); doneCerts.Add(cert.Certificate); } foreach (CertId certId in _chainCerts.Keys) { var cert = (X509CertificateEntry) _chainCerts[certId]; if (doneCerts.Contains(cert.Certificate)) { continue; } var cBag = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(cert.Certificate.GetEncoded())); var fName = new Asn1EncodableVector(); foreach (string oid in cert.BagAttributeKeys) { // a certificate not immediately linked to a key doesn't require // a localKeyID and will confuse some PKCS12 implementations. // // If we find one, we'll prune it out. if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id)) { continue; } fName.Add(new DerSequence(new DerObjectIdentifier(oid), new DerSet(cert[oid]))); } var sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)); certSeq.Add(sBag); } derEncodedBytes = new DerSequence(certSeq).GetDerEncoded(); byte[] certBytes = CryptPbeData(true, cAlgId, password, false, derEncodedBytes); var cInfo = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes)); ContentInfo[] info = {new ContentInfo(PkcsObjectIdentifiers.Data, keyString), new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object())}; byte[] data = new AuthenticatedSafe(info).GetEncoded(_useDerEncoding ? Asn1Encodable.Der : Asn1Encodable.Ber); var mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(data)); // // create the mac // var mSalt = new byte[20]; random.NextBytes(mSalt); byte[] mac = CalculatePbeMac(OiwObjectIdentifiers.IdSha1, mSalt, MinIterations, password, false, data); var algId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance); var dInfo = new DigestInfo(algId, mac); var mData = new MacData(dInfo, mSalt, MinIterations); // // output the Pfx // var pfx = new Pfx(mainInfo, mData); DerOutputStream derOut; if (_useDerEncoding) { derOut = new DerOutputStream(stream); } else { derOut = new BerOutputStream(stream); } derOut.WriteObject(pfx); }
// private string GetHexEncoded(byte[] bytes) // { // bytes = Hex.Encode(bytes); // // char[] chars = new char[bytes.Length]; // // for (int i = 0; i != bytes.Length; i++) // { // chars[i] = (char)bytes[i]; // } // // return new string(chars); // } private PemObject CreatePemObject( object obj, string algorithm, char[] password, SecureRandom random) { if (obj == null) throw new ArgumentNullException("obj"); if (algorithm == null) throw new ArgumentNullException("algorithm"); if (password == null) throw new ArgumentNullException("password"); if (random == null) throw new ArgumentNullException("random"); if (obj is AsymmetricCipherKeyPair) { return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private, algorithm, password, random); } string type = null; byte[] keyData = null; if (obj is AsymmetricKeyParameter) { AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj; if (akp.IsPrivate) { string keyType; keyData = EncodePrivateKey(akp, out keyType); type = keyType + " PRIVATE KEY"; } } if (type == null || keyData == null) { // TODO Support other types? throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName); } string dekAlgName = algorithm.ToUpperInvariant(); // Note: For backward compatibility if (dekAlgName == "DESEDE") { dekAlgName = "DES-EDE3-CBC"; } int ivLength = dekAlgName.StartsWith("AES-") ? 16 : 8; byte[] iv = new byte[ivLength]; random.NextBytes(iv); byte[] encData = PemUtilities.Crypt(true, keyData, password, dekAlgName, iv); IList headers = Platform.CreateArrayList(2); headers.Add(new PemHeader("Proc-Type", "4,ENCRYPTED")); headers.Add(new PemHeader("DEK-Info", dekAlgName + "," + Hex.ToHexString(iv))); return new PemObject(type, headers, encData); }
public static KeyParameter MakeRandomKey( SymmetricKeyAlgorithmTag algorithm, SecureRandom random) { int keySize = GetKeySize(algorithm); byte[] keyBytes = new byte[(keySize + 7) / 8]; random.NextBytes(keyBytes); return MakeKey(algorithm, keyBytes); }
private static byte[] CreateIV( SecureRandom random, int ivLength) { byte[] iv = new byte[ivLength]; random.NextBytes(iv); return iv; }
private static byte[] EncryptKeyData( byte[] rawKeyData, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, SecureRandom random, out S2k s2k, out byte[] iv) { IBufferedCipher c; try { string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm); c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } byte[] s2kIV = new byte[8]; random.NextBytes(s2kIV); s2k = new S2k(HashAlgorithmTag.Sha1, s2kIV, 0x60); KeyParameter kp = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase); iv = new byte[c.GetBlockSize()]; random.NextBytes(iv); c.Init(true, new ParametersWithRandom(new ParametersWithIV(kp, iv), random)); return c.DoFinal(rawKeyData); }