Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.bouncycastle.crypto.macs;
  
Poly1305 message authentication code, designed by D. J. Bernstein.

Poly1305 computes a 128-bit (16 bytes) authenticator, using a 128 bit nonce and a 256 bit key consisting of a 128 bit key applied to an underlying cipher, and a 128 bit key (with 106 effective key bits) used in the authenticator.

The polynomial calculation in this implementation is adapted from the public domain poly1305-donna-unrolled C implementation by Andrew M (@floodyberry).

 
 public class Poly1305
     implements Mac
 {
     private static final int BLOCK_SIZE = 16;
 
     private final BlockCipher cipher;
 
     private final byte[] singleByte = new byte[1];
 
     // Initialised state
 
    
Polynomial key
 
     private int r0r1r2r3r4;

    
Precomputed 5 * r[1..4]
 
     private int s1s2s3s4;

    
Encrypted nonce
 
     private int k0k1k2k3;
 
     // Accumulating state
 
    
Current block of buffered input
 
     private final byte[] currentBlock = new byte[];

    
Current offset in input buffer
 
     private int currentBlockOffset = 0;

    
Polynomial accumulator
 
     private int h0h1h2h3h4;

    
Constructs a Poly1305 MAC, where the key passed to init() will be used directly.
 
     public Poly1305()
     {
         this. = null;
     }

    
Constructs a Poly1305 MAC, using a 128 bit block cipher.
 
     public Poly1305(final BlockCipher cipher)
     {
         if (cipher.getBlockSize() != )
         {
             throw new IllegalArgumentException("Poly1305 requires a 128 bit block cipher.");
         }
         this. = cipher;
     }

    
Initialises the Poly1305 MAC.

Parameters:
params if used with a block cipher, then a org.bouncycastle.crypto.params.ParametersWithIV containing a 128 bit nonce and a org.bouncycastle.crypto.params.KeyParameter with a 256 bit key complying to the Poly1305 key format, otherwise just the org.bouncycastle.crypto.params.KeyParameter.
 
     public void init(CipherParameters params)
         throws IllegalArgumentException
     {
         byte[] nonce = null;
 
         if ( != null)
         {
             if (!(params instanceof ParametersWithIV))
             {
                 throw new IllegalArgumentException("Poly1305 requires an IV when used with a block cipher.");
             }
             
             ParametersWithIV ivParams = (ParametersWithIV)params;
             nonce = ivParams.getIV();
             params = ivParams.getParameters();
         }
 
        if (!(params instanceof KeyParameter))
        {
            throw new IllegalArgumentException("Poly1305 requires a key.");
        }
        KeyParameter keyParams = (KeyParameter)params;
        setKey(keyParams.getKey(), nonce);
        reset();
    }
    private void setKey(final byte[] keyfinal byte[] nonce)
    {
        if ( != null && (nonce == null || nonce.length != ))
        {
            throw new IllegalArgumentException("Poly1305 requires a 128 bit IV.");
        }
        Poly1305KeyGenerator.checkKey(key);
        // Extract r portion of key
        int t0 = Pack.littleEndianToInt(key + 0);
        int t1 = Pack.littleEndianToInt(key + 4);
        int t2 = Pack.littleEndianToInt(key + 8);
        int t3 = Pack.littleEndianToInt(key + 12);
         = t0 & 0x3ffffff; t0 >>>= 26; t0 |= t1 << 6;
         = t0 & 0x3ffff03; t1 >>>= 20; t1 |= t2 << 12;
         = t1 & 0x3ffc0ff; t2 >>>= 14; t2 |= t3 << 18;
         = t2 & 0x3f03fff; t3 >>>= 8;
         = t3 & 0x00fffff;
        // Precompute multipliers
         =  * 5;
         =  * 5;
         =  * 5;
         =  * 5;
        final byte[] kBytes;
        if ( == null)
        {
            kBytes = key;
        }
        else
        {
            // Compute encrypted nonce
            kBytes = new byte[];
            .init(truenew KeyParameter(key, 0, ));
            .processBlock(nonce, 0, kBytes, 0);
        }
         = Pack.littleEndianToInt(kBytes, 0);
         = Pack.littleEndianToInt(kBytes, 4);
         = Pack.littleEndianToInt(kBytes, 8);
         = Pack.littleEndianToInt(kBytes, 12);
    }
    public String getAlgorithmName()
    {
        return  == null ? "Poly1305" : "Poly1305-" + .getAlgorithmName();
    }
    public int getMacSize()
    {
        return ;
    }
    public void update(final byte in)
        throws IllegalStateException
    {
        [0] = in;
        update(, 0, 1);
    }
    public void update(final byte[] infinal int inOfffinal int len)
        throws DataLengthException,
        IllegalStateException
    {
        int copied = 0;
        while (len > copied)
        {
            if ( == )
            {
                processBlock();
                 = 0;
            }
            int toCopy = Math.min((len - copied),  - );
            System.arraycopy(incopied + inOfftoCopy);
            copied += toCopy;
             += toCopy;
        }
    }
    private void processBlock()
    {
        if ( < )
        {
            [] = 1;
            for (int i =  + 1; i < i++)
            {
                [i] = 0;
            }
        }
        final long t0 = 0xffffffffL & Pack.littleEndianToInt(, 0);
        final long t1 = 0xffffffffL & Pack.littleEndianToInt(, 4);
        final long t2 = 0xffffffffL & Pack.littleEndianToInt(, 8);
        final long t3 = 0xffffffffL & Pack.littleEndianToInt(, 12);
         += t0 & 0x3ffffff;
         += (((t1 << 32) | t0) >>> 26) & 0x3ffffff;
         += (((t2 << 32) | t1) >>> 20) & 0x3ffffff;
         += (((t3 << 32) | t2) >>> 14) & 0x3ffffff;
         += (t3 >>> 8);
        if ( == )
        {
             += (1 << 24);
        }
        long tp0 = mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,);
        long tp1 = mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,);
        long tp2 = mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,);
        long tp3 = mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,);
        long tp4 = mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,) + mul32x32_64(,);
        long b;
         = (int)tp0 & 0x3ffffff; b = (tp0 >>> 26);
        tp1 += b = (int)tp1 & 0x3ffffff; b = ((tp1 >>> 26) & 0xffffffff);
        tp2 += b = (int)tp2 & 0x3ffffff; b = ((tp2 >>> 26) & 0xffffffff);
        tp3 += b = (int)tp3 & 0x3ffffff; b = (tp3 >>> 26);
        tp4 += b = (int)tp4 & 0x3ffffff; b = (tp4 >>> 26);
         += b * 5;
    }
    public int doFinal(final byte[] outfinal int outOff)
        throws DataLengthException,
        IllegalStateException
    {
        if (outOff +  > out.length)
        {
            throw new DataLengthException("Output buffer is too short.");
        }
        if ( > 0)
        {
            // Process padded final block
            processBlock();
        }
        long f0f1f2f3;
        int b =  >>> 26;
         =  & 0x3ffffff;
         += bb =  >>> 26;  =  & 0x3ffffff;
         += bb =  >>> 26;  =  & 0x3ffffff;
         += bb =  >>> 26;  =  & 0x3ffffff;
         += bb =  >>> 26;  =  & 0x3ffffff;
         += b * 5;
        int g0g1g2g3g4;
        g0 =  + 5; b = g0 >>> 26; g0 &= 0x3ffffff;
        g1 =  + bb = g1 >>> 26; g1 &= 0x3ffffff;
        g2 =  + bb = g2 >>> 26; g2 &= 0x3ffffff;
        g3 =  + bb = g3 >>> 26; g3 &= 0x3ffffff;
        g4 =  + b - (1 << 26);
        b = (g4 >>> 31) - 1;
        int nb = ~b;
         = ( & nb) | (g0 & b);
         = ( & nb) | (g1 & b);
         = ( & nb) | (g2 & b);
         = ( & nb) | (g3 & b);
         = ( & nb) | (g4 & b);
        f0 = (((       ) | ( << 26)) & 0xffffffffl) + (0xffffffffL & );
        f1 = ((( >>> 6 ) | ( << 20)) & 0xffffffffl) + (0xffffffffL & );
        f2 = ((( >>> 12) | ( << 14)) & 0xffffffffl) + (0xffffffffL & );
        f3 = ((( >>> 18) | ( << 8 )) & 0xffffffffl) + (0xffffffffL & );
        Pack.intToLittleEndian((int)f0outoutOff);
        f1 += (f0 >>> 32);
        Pack.intToLittleEndian((int)f1outoutOff + 4);
        f2 += (f1 >>> 32);
        Pack.intToLittleEndian((int)f2outoutOff + 8);
        f3 += (f2 >>> 32);
        Pack.intToLittleEndian((int)f3outoutOff + 12);
        reset();
        return ;
    }
    public void reset()
    {
         = 0;
         =  =  =  =  = 0;
    }
    private static final long mul32x32_64(int i1int i2)
    {
        return ((long)i1) * i2;
    }
New to GrepCode? Check out our FAQ X