text: #include "../include/ed25519.h"
  #include "../include/ge.h"
  #include "../include/sc.h"
  #include "../include/sha512.h"
  
  
  /* see http://crypto.stackexchange.com/a/6215/4697 */
  void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
      const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
      
      unsigned char n[32]; 
      ge_p3 nB;
      ge_p1p1 A_p1p1;
      ge_p3 A;
      ge_p3 public_key_unpacked;
      ge_cached T;
  
      sha512_context hash;
      unsigned char hashbuf[64];
  
      int i;
  
      /* copy the scalar and clear highest bit */
      for (i = 0; i < 31; ++i) {
          n[i] = scalar[i];
      }
      n[31] = scalar[31] & 127;
  
      /* private key: a = n + t */
      if (private_key) {
          sc_muladd(private_key, SC_1, n, private_key);
  
          // https://github.com/orlp/ed25519/issues/3
          sha512_init(&hash);
          sha512_update(&hash, private_key + 32, 32);
          sha512_update(&hash, scalar, 32);
          sha512_final(&hash, hashbuf);
          for (i = 0; i < 32; ++i) {
              private_key[32 + i] = hashbuf[i];
          }
      }
  
      /* public key: A = nB + T */
      if (public_key) {
          /* if we know the private key we don't need a point addition, which is faster */
          /* using a "timing attack" you could find out wether or not we know the private
             key, but this information seems rather useless - if this is important pass
             public_key and private_key seperately in 2 function calls */
          if (private_key) {
              ge_scalarmult_base(&A, private_key);
          } else {
              /* unpack public key into T */
              ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
              fe_neg(public_key_unpacked.X, public_key_unpacked.X); /* undo negate */
              fe_neg(public_key_unpacked.T, public_key_unpacked.T); /* undo negate */
              ge_p3_to_cached(&T, &public_key_unpacked);
  
              /* calculate n*B */
              ge_scalarmult_base(&nB, n);
  
              /* A = n*B + T */
              ge_add(&A_p1p1, &nB, &T);
              ge_p1p1_to_p3(&A, &A_p1p1);
          }
              
          /* pack public key */
          ge_p3_tobytes(public_key, &A);
      }
  }
  