diff options
Diffstat (limited to '')
-rw-r--r-- | src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java b/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java new file mode 100644 index 00000000..9dd1dbee --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java @@ -0,0 +1,75 @@ +/** + * Copyright (C) 2014 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package org.whispersystems.libaxolotl.ratchet; + + +import org.whispersystems.libaxolotl.kdf.DerivedMessageSecrets; +import org.whispersystems.libaxolotl.kdf.HKDF; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class ChainKey { + + private static final byte[] MESSAGE_KEY_SEED = {0x01}; + private static final byte[] CHAIN_KEY_SEED = {0x02}; + + private final HKDF kdf; + private final byte[] key; + private final int index; + + public ChainKey(HKDF kdf, byte[] key, int index) { + this.kdf = kdf; + this.key = key; + this.index = index; + } + + public byte[] getKey() { + return key; + } + + public int getIndex() { + return index; + } + + public ChainKey getNextChainKey() { + byte[] nextKey = getBaseMaterial(CHAIN_KEY_SEED); + return new ChainKey(kdf, nextKey, index + 1); + } + + public MessageKeys getMessageKeys() { + byte[] inputKeyMaterial = getBaseMaterial(MESSAGE_KEY_SEED); + byte[] keyMaterialBytes = kdf.deriveSecrets(inputKeyMaterial, "WhisperMessageKeys".getBytes(), DerivedMessageSecrets.SIZE); + DerivedMessageSecrets keyMaterial = new DerivedMessageSecrets(keyMaterialBytes); + + return new MessageKeys(keyMaterial.getCipherKey(), keyMaterial.getMacKey(), keyMaterial.getIv(), index); + } + + private byte[] getBaseMaterial(byte[] seed) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(key, "HmacSHA256")); + + return mac.doFinal(seed); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new AssertionError(e); + } + } +} |