public ProvisionMessage Decrypt(IdentityKeyPair tmpIdentity, byte[] message) { ProvisionEnvelope env = ProvisionEnvelope.Parser.ParseFrom(message); ECPublicKey publicKey = Curve.decodePoint(env.PublicKey.ToByteArray(), 0); byte[] sharedSecret = Curve.calculateAgreement(publicKey, tmpIdentity.getPrivateKey()); byte[] derivedSecret = new HKDFv3().deriveSecrets(sharedSecret, Encoding.UTF8.GetBytes("TextSecure Provisioning Message"), 64); byte[][] parts = Util.Split(derivedSecret, 32, 32); byte[] joined = env.Body.ToByteArray(); if (joined[0] != 0x01) { throw new Exception("Bad version number on provision message!"); } byte[] iv = new byte[16]; Array.Copy(joined, 1, iv, 0, 16); byte[] ciphertext = new byte[joined.Length - 32 - 17]; Array.Copy(joined, 17, ciphertext, 0, joined.Length - 32 - 17); byte[] ivAndCiphertext = new byte[joined.Length - 32]; Array.Copy(joined, ivAndCiphertext, joined.Length - 32); byte[] mac = new byte[32]; Array.Copy(joined, joined.Length - 32, mac, 0, 32); VerifyMac(parts[1], ivAndCiphertext, mac); return(ProvisionMessage.Parser.ParseFrom(Decrypt(parts[0], iv, ciphertext))); }
private StaticKeys CalculateStaticKeys(ECPublicKey staticPublic, ECPrivateKey staticPrivate, byte[] salt) { byte[] staticSecret = Curve.calculateAgreement(staticPublic, staticPrivate); byte[] staticDerived = new HKDFv3().deriveSecrets(staticSecret, salt, new byte[0], 96); byte[][] staticDerivedParts = ByteUtil.split(staticDerived, 32, 32, 32); return(new StaticKeys(staticDerivedParts[1], staticDerivedParts[2])); }
private EphemeralKeys CalculateEphemeralKeys(ECPublicKey ephemeralPublic, ECPrivateKey ephemeralPrivate, byte[] salt) { byte[] ephemeralSecret = Curve.calculateAgreement(ephemeralPublic, ephemeralPrivate); byte[] ephemeralDerived = new HKDFv3().deriveSecrets(ephemeralSecret, salt, new byte[0], 96); byte[][] ephemeralDerivedParts = ByteUtil.split(ephemeralDerived, 32, 32, 32); return(new EphemeralKeys(ephemeralDerivedParts[0], ephemeralDerivedParts[1], ephemeralDerivedParts[2])); }
private static DerivedKeys calculateDerivedKeys(byte[] masterSecret) { HKDF kdf = new HKDFv3(); byte[] derivedSecretBytes = kdf.deriveSecrets(masterSecret, Encoding.UTF8.GetBytes("WhisperText"), 64); byte[][] derivedSecrets = ByteUtil.split(derivedSecretBytes, 32, 32); return(new DerivedKeys(new RootKey(kdf, derivedSecrets[0]), new ChainKey(kdf, derivedSecrets[1], 0))); }
public SenderMessageKey(uint iteration, byte[] seed) { byte[] derivative = new HKDFv3().deriveSecrets(seed, Encoding.UTF8.GetBytes("WhisperGroup"), 48); byte[][] parts = ByteUtil.split(derivative, 16, 32); this.iteration = iteration; this.seed = seed; this.iv = parts[0]; this.cipherKey = parts[1]; }
public byte[] encrypt(ProvisionMessage message)// throws InvalidKeyException { ECKeyPair ourKeyPair = Curve.generateKeyPair(); byte[] sharedSecret = Curve.calculateAgreement(theirPublicKey, ourKeyPair.getPrivateKey()); byte[] derivedSecret = new HKDFv3().deriveSecrets(sharedSecret, Encoding.UTF8.GetBytes("TextSecure Provisioning Message"), 64); byte[][] parts = Util.split(derivedSecret, 32, 32); byte[] version = { 0x01 }; byte[] ciphertext = getCiphertext(parts[0], message.ToByteArray()); byte[] mac = getMac(parts[1], Util.join(version, ciphertext)); byte[] body = Util.join(version, ciphertext, mac); return(ProvisionEnvelope.CreateBuilder() .SetPublicKey(ByteString.CopyFrom(ourKeyPair.getPublicKey().serialize())) .SetBody(ByteString.CopyFrom(body)) .Build() .ToByteArray()); }