[cpp-sp] branch main updated: Switch RNG to C++ impl.

Codeberg noreply at shibboleth.net
Mon Sep 7 18:16:42 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository cpp-sp.

View the commit online:
https://codeberg.org/Shibboleth/cpp-sp/commit/b23526331f556b99dfb550ace585b562b3956d3a

The following commit(s) were added to refs/heads/main by this push:
     new b2352633 Switch RNG to C++ impl.
b2352633 is described below

commit b23526331f556b99dfb550ace585b562b3956d3a
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon Sep 7 14:16:27 2026 -0400

    Switch RNG to C++ impl.
---
 shibsp/Makefile.am            |   4 -
 shibsp/csprng/csprng.h        |  50 -----------
 shibsp/csprng/csprng.hpp      | 195 ------------------------------------------
 shibsp/csprng/impl/csprng.cpp | 137 -----------------------------
 shibsp/csprng/is_iterable.hpp |  46 ----------
 shibsp/impl/AgentConfig.cpp   |  45 +++++++++-
 6 files changed, 42 insertions(+), 435 deletions(-)

diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index e8d0c61f..d11aae09 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -83,9 +83,6 @@ utilinclude_HEADERS = \
 
 noinst_HEADERS = \
 	internal.h \
-	csprng/csprng.h \
-	csprng/csprng.hpp \
-	csprng/is_iterable.hpp \
 	logging/impl/AbstractLoggingService.h \
 	logging/impl/LoggingServiceSPI.h \
 	logging/impl/StringUtil.h \
@@ -102,7 +99,6 @@ libshibsp_la_SOURCES = \
 	exceptions.cpp \
 	version.cpp \
 	attribute/impl/DefaultAttributeConfiguration.cpp \
-	csprng/impl/csprng.cpp \
 	handler/impl/AbstractHandler.cpp \
 	handler/impl/AttributeCheckerHandler.cpp \
 	handler/impl/DefaultHandlerConfiguration.cpp \
diff --git a/shibsp/csprng/csprng.h b/shibsp/csprng/csprng.h
deleted file mode 100644
index b49f338d..00000000
--- a/shibsp/csprng/csprng.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-// Interface to the OS Cryptographically-Secure Pseudo-Random Number Generator
-
-// Copyright 2017 Michael Thomas Greer
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file ../../LICENSE_1_0.txt or copy at
-//  http://www.boost.org/LICENSE_1_0.txt )
-*/
-
-#pragma once
-#ifndef DUTHOMHAS_CSPRNG_H
-#define DUTHOMHAS_CSPRNG_H
-
-/* ------------------------------------------------------------------------------------------------
- * CSPRNG
- */
-typedef void* CSPRNG;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-CSPRNG csprng_create();
-/* Returns a new CSPRNG object, 0 on error.
- */
-
-int csprng_get( CSPRNG, void* dest, unsigned long long size );
-/* Fills $dest with $size bytes worth of random data.
- * Returns 1 on succes, 0 on failure.
- */
-
-long csprng_get_int( CSPRNG );
-/* Return a random value
- * There is no way to know if it failed.
- * (If it did fail, the result will be 0, which is fairly unlikely
- *  to occur multiple times in sequence.
- *  It is also unlikely to fail at all if csprng_create() succeeded.)
- */
-
-CSPRNG csprng_destroy( CSPRNG );
-/* Destroy an existing CSPRNG object. Returns 0.
- * Use it as:
- *   v = csprng_destroy( v );
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/shibsp/csprng/csprng.hpp b/shibsp/csprng/csprng.hpp
deleted file mode 100644
index 9e3dc1eb..00000000
--- a/shibsp/csprng/csprng.hpp
+++ /dev/null
@@ -1,195 +0,0 @@
-// Interface to the OS Cryptographically-Secure Pseudo-Random Number Generator
-
-// Copyright 2017 Michael Thomas Greer
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file ../../LICENSE_1_0.txt or copy at
-//  http://www.boost.org/LICENSE_1_0.txt )
-
-#ifndef DUTHOMHAS_CSPRNG_HPP
-#define DUTHOMHAS_CSPRNG_HPP
-
-#include <shibsp/base.h>
-#include <shibsp/csprng/csprng.h>
-#include <shibsp/csprng/is_iterable.hpp>
-
-#include <initializer_list>
-#include <iterator>
-#include <limits>
-#include <stdexcept>
-#include <string>
-#include <type_traits>
-
-//-------------------------------------------------------------------------------------------------
-namespace duthomhas
-{
-  struct csprng
-  {
-    // Standard C++ Library PRNG boilerplate  . . . . . . . . . . . . . . . . . . . . . .
-    typedef unsigned long result_type;
-
-    static constexpr result_type min() { return std::numeric_limits <result_type> ::min(); }
-    static constexpr result_type max() { return std::numeric_limits <result_type> ::max(); }
-
-    template <typename Sseq>
-    void seed( Sseq& ) { }
-    void seed( result_type ) { }
-    void discard( unsigned long long ) { }
-
-  public:
-    // Standard C++ std::seed_seq boilerplate . . . . . . . . . . . . . . . . . . . . . .
-    template <typename Iterator>
-    csprng( Iterator begin, Iterator end ):
-      internal( csprng_create() ),
-      sseq( internal, std::distance( begin, end ) )
-      { }
-
-    template <typename T>
-    csprng( std::initializer_list <T> xs ):
-      internal( csprng_create() ),
-      sseq( internal, xs.size() )
-      { }
-
-    struct sseq_type
-    {
-      // ( This is separated out like this otherwise objects that take a SeedSeq
-      //   object may get confused by the conversion operators in the main class. )
-
-      template <typename Iterator>
-      void generate( Iterator begin, Iterator end )
-      {
-        while (begin != end)
-          *begin++ = csprng_get_int( internal );
-      }
-
-      std::size_t size() const { return seed_seq_size; }
-
-      template <typename Iterator>
-      void param( Iterator dest ) const
-      {
-        for (auto n = seed_seq_size; n--; )
-          *dest++ = csprng_get_int( internal );
-      }
-
-      CSPRNG& internal;
-      std::size_t seed_seq_size;
-
-      sseq_type( CSPRNG& internal, std::size_t seed_seq_size ):
-        internal( internal ),
-        seed_seq_size( seed_seq_size )
-        { }
-    };
-
-  public:
-    // Runtime errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-    struct exception: public std::runtime_error
-    {
-      exception( const char*        message ): std::runtime_error( message ) { }
-      exception( const std::string& message ): std::runtime_error( message ) { }
-    };
-
-    // Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-    csprng(): internal( csprng_create() ), sseq( internal, 0 )
-    {
-      if (!internal)
-        throw exception( "duthomhas::CSPRNG: Failed to initialize the OS CSPRNG" );
-    }
-
-    csprng( const csprng& that ):
-      internal( csprng_create() ),
-      sseq( internal, that.sseq.seed_seq_size )
-    {
-      if (!internal)
-        throw exception( "duthomhas::CSPRNG: Failed to initialize the OS CSPRNG" );
-    }
-
-    // Destructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-   ~csprng()
-    {
-      internal = csprng_destroy( internal );
-    }
-
-    // Typed buffer fill  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-    //   int* xs = rng( new int[ 5 ], 5 );
-    template <typename T>
-    T* operator () ( T* buffer, std::size_t n )
-    {
-      if (!csprng_get( internal, (void*)buffer, n * sizeof(T) ))
-        throw exception( "duthomhas::CSPRNG: Failed to read the OS CSPRNG" );
-      return buffer;
-    }
-
-    // Untyped buffer fill  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-    //   void* p = get_some_unknown_with_known_size_in_bytes();
-    //   rng( p, size_in_bytes );
-//    template <typename T>
-    void* operator () ( void* buffer, std::size_t n )
-    {
-      return operator () <unsigned char> ( (unsigned char*)buffer, n );
-    }
-
-    // Typed assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-    //   int x = rng();
-    template <typename T>
-    operator T ()
-    {
-      T result;
-      return operator () ( result );
-    }
-
-    // Untyped function --> unsigned long . . . . . . . . . . . . . . . . . . . . . . . .
-    //   rng()
-    result_type operator () ()
-    {
-      result_type result;
-      return *operator () ( &result, 1 );
-    }
-
-    // Fundamental / assignable from fundamental types function . . . . . . . . . . . . .
-    //   rng( int() )
-    //
-    //   int x;
-    //   rng( x )
-    template <typename T>
-    typename std::enable_if <std::is_fundamental <typename std::remove_reference <T> ::type> ::value, T&> ::type
-    operator () ( T&& value )
-    {
-      operator () ( &value, 1 );
-      return value;
-    }
-
-    // Iterable types function  . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-    //   auto s = rng( std::string( 20, 0 ) );
-    //   auto v = rng( std::vector <int> ( 20 ) );
-    template <typename Iterable>
-    typename std::enable_if <is_iterable <Iterable> ::value, Iterable&> ::type
-    operator () ( Iterable&& value )
-    {
-      for (auto& v : value)
-        operator () ( v );
-      return value;
-    }
-
-    // Array types function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-    //   int xs[ 20 ];
-    //   rng( xs )
-    template <typename T, std::size_t N>
-    T* operator () ( T* (&array)[ N ] )
-    {
-      for (auto& v : array)
-        operator () ( v );
-      return &(array[0]);
-    }
-
-  private:
-    // Internal state is hidden from user . . . . . . . . . . . . . . . . . . . . . . . .
-    CSPRNG internal;
-    
-  public:
-    // This thing is public, though . . . . . . . . . . . . . . . . . . . . . . . . . . .
-    sseq_type sseq;
-
-  };
-
-}
-
-#endif
diff --git a/shibsp/csprng/impl/csprng.cpp b/shibsp/csprng/impl/csprng.cpp
deleted file mode 100644
index e06dd099..00000000
--- a/shibsp/csprng/impl/csprng.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-// Source for the OS Cryptographically-Secure Pseudo-Random Number Generator
-
-// Copyright 2017 Michael Thomas Greer
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file ../LICENSE_1_0.txt or copy at
-//  http://www.boost.org/LICENSE_1_0.txt )
-*/
-
-#include "csprng/csprng.h"
-
-/* ///////////////////////////////////////////////////////////////////////////////////////////// */
-#ifdef _WIN32
-/* ///////////////////////////////////////////////////////////////////////////////////////////// */
-
-  #include <windows.h>
-  #include <wincrypt.h>
-
-  #ifdef _MSC_VER
-  #pragma comment(lib, "advapi32.lib")
-  #endif
-  
-  #ifdef __cplusplus
-  extern "C" {
-  #endif
-
-  /* ------------------------------------------------------------------------------------------- */
-  typedef union
-  {
-    CSPRNG     object;
-    HCRYPTPROV hCryptProv;
-  }
-  CSPRNG_TYPE;
-
-  /* ------------------------------------------------------------------------------------------- */
-  CSPRNG csprng_create()
-  {
-    CSPRNG_TYPE csprng;
-    if (!CryptAcquireContextA( &csprng.hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT ))
-      csprng.hCryptProv = 0;
-    return csprng.object;
-  }
-
-  /* ------------------------------------------------------------------------------------------- */
-  int csprng_get( CSPRNG object, void* dest, unsigned long long size )
-  {
-    // Alas, we have to be pedantic here. csprng_get().size is a 64-bit entity.
-    // However, CryptGenRandom().size is only a 32-bit DWORD. So we have to make sure failure 
-    // isn't from providing less random data than requested, even if absurd.
-    unsigned long long n;
-    
-    CSPRNG_TYPE csprng;
-    csprng.object = object;
-    if (!csprng.hCryptProv) return 0;
-    
-    n = size >> 30;
-    while (n--)
-      if (!CryptGenRandom( csprng.hCryptProv, 1UL << 30, (BYTE*)dest )) return 0;
-      
-    return !!CryptGenRandom( csprng.hCryptProv, size & ((1ULL << 30) - 1), (BYTE*)dest );
-  }
-
-  /* ------------------------------------------------------------------------------------------- */
-  long csprng_get_int( CSPRNG object )
-  {
-    long result;
-    return csprng_get( object, &result, sizeof(result) ) ? result : 0;
-  }
-
-  /* ------------------------------------------------------------------------------------------- */
-  CSPRNG csprng_destroy( CSPRNG object )
-  {
-    CSPRNG_TYPE csprng;
-    csprng.object = object;
-    if (csprng.hCryptProv) CryptReleaseContext( csprng.hCryptProv, 0 );
-    return 0;
-  }
-
-  #ifdef __cplusplus
-  }
-  #endif
-
-/* ///////////////////////////////////////////////////////////////////////////////////////////// */
-#else  /* Using /dev/urandom                                                                     */
-/* ///////////////////////////////////////////////////////////////////////////////////////////// */
-
-  #include <stdio.h>
-
-  #ifdef __cplusplus
-  extern "C" {
-  #endif
-
-  /* ------------------------------------------------------------------------------------------- */
-  typedef union
-  {
-    CSPRNG object;
-    FILE*  urandom;
-  }
-  CSPRNG_TYPE;
-
-  /* ------------------------------------------------------------------------------------------- */
-  CSPRNG csprng_create()
-  {
-    CSPRNG_TYPE csprng;
-    csprng.urandom = fopen( "/dev/urandom", "rb" );
-    return csprng.object;
-  }
-
-  /* ------------------------------------------------------------------------------------------- */
-  int csprng_get( CSPRNG object, void* dest, unsigned long long size )
-  {
-    CSPRNG_TYPE csprng;
-    csprng.object = object;
-    return (csprng.urandom) && (fread( (char*)dest, 1, size, csprng.urandom ) == size);
-  }
-
-  /* ------------------------------------------------------------------------------------------- */
-  long csprng_get_int( CSPRNG object )
-  {
-    long result;
-    return csprng_get( object, &result, sizeof(result) ) ? result : 0;
-  }
-
-  /* ------------------------------------------------------------------------------------------- */
-  CSPRNG csprng_destroy( CSPRNG object )
-  {
-    CSPRNG_TYPE csprng;
-    csprng.object = object;
-    if (csprng.urandom) fclose( csprng.urandom );
-    return 0;
-  }
-  
-  #ifdef __cplusplus
-  }
-  #endif
-
-#endif
diff --git a/shibsp/csprng/is_iterable.hpp b/shibsp/csprng/is_iterable.hpp
deleted file mode 100644
index cb991909..00000000
--- a/shibsp/csprng/is_iterable.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-// is_iterable.hpp
-
-// Copyright 2017 Michael Thomas Greer
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file ../../LICENSE_1_0.txt or copy at
-//  http://www.boost.org/LICENSE_1_0.txt )
-
-#ifndef DUTHOMHAS_IS_ITERABLE_HPP
-#define DUTHOMHAS_IS_ITERABLE_HPP
-
-namespace duthomhas
-{
-
-  // The basis for this code was found at
-  // https://stackoverflow.com/a/29634934/2706707
-  using std::begin;
-  using std::end;
-
-  template <typename T>
-  class is_iterable
-  {
-    template <typename U>
-    static constexpr auto is_iterable_impl( int ) 
-      -> decltype(
-           begin( std::declval <U&> () ) != end( std::declval <U&> () ),   // begin/end and operator !=
-           void(),                                                         // Handle evil operator ,
-           ++std::declval <decltype( begin( std::declval <U&> () ) )&> (), // operator ++
-           void( *begin( std::declval <U&> () ) ),                         // operator*
-           std::true_type {}
-         )
-    { return std::true_type {}; }
-  
-    template <typename U>
-    static constexpr std::false_type is_iterable_impl(...)
-    { return std::false_type {}; }
-  
-    typedef decltype( is_iterable_impl <T> ( 0 ) ) type;
-    
-  public:
-    //static constexpr bool value = type::value;
-    enum : bool { value = type::value };
-  };
-
-}
-
-#endif
diff --git a/shibsp/impl/AgentConfig.cpp b/shibsp/impl/AgentConfig.cpp
index 8389c871..bc9432d5 100644
--- a/shibsp/impl/AgentConfig.cpp
+++ b/shibsp/impl/AgentConfig.cpp
@@ -26,7 +26,6 @@
 #include "Agent.h"
 #include "AgentConfig.h"
 #include "RequestMapper.h"
-#include "csprng/csprng.hpp"
 #include "handler/Handler.h"
 #include "io/HTTPResponse.h"
 #include "logging/LoggingService.h"
@@ -39,6 +38,7 @@
 
 #include <climits>
 #include <ctime>
+#include <random>
 #include <stdexcept>
 #include <thread>
 #include <mutex>
@@ -108,7 +108,7 @@ namespace shibsp {
         vector<void*> m_libhandles;
         unique_ptr<LoggingService> m_logging;
         unique_ptr<Agent> m_agent;
-        mutable duthomhas::csprng m_rng;
+        mutable mt19937_64 m_rng;
     };
     
     static AgentInternalConfig g_agentConfig;
@@ -166,7 +166,23 @@ Agent& AgentInternalConfig::getAgent() const
 
 string AgentInternalConfig::generateRandom(unsigned int len) const
 {
-    return hex_encode(m_rng(string(len, 0)));
+    string s;
+
+    while (len > 0) {
+        uint_fast64_t val = m_rng();
+        size_t randlen = sizeof(uint_fast64_t);
+        for (int i = 0; i < randlen; ++i) {
+            s += (char) (val & 0xFF);
+            val = val >> 8;
+        }
+        if (len > randlen) {
+            len -= randlen;
+        } else {
+            len = 0;
+        }
+    }
+
+    return hex_encode(s);
 }
 
 bool AgentInternalConfig::init(const char* inst_prefix, const char* config_file, bool rethrow)
@@ -193,8 +209,31 @@ bool AgentInternalConfig::init(const char* inst_prefix, const char* config_file,
     return true;
 }
 
+static unsigned long long my_entropy()
+{
+    // Gather many potential forms of entropy and XOR them
+    const  uint64_t my_seed = 0xc587acf84d9d5a64;
+    static uint64_t i = 0;        
+    static std::random_device rd; 
+    const auto hrclock = std::chrono::high_resolution_clock::now().time_since_epoch().count();
+    const auto sclock  = std::chrono::system_clock::now().time_since_epoch().count();
+    auto *heap = malloc(1);
+    const auto mash = my_seed + rd() + hrclock + sclock + (i++) +
+        reinterpret_cast<intptr_t>(heap) + reinterpret_cast<intptr_t>(&hrclock) +
+        reinterpret_cast<intptr_t>(&i) + reinterpret_cast<intptr_t>(&malloc) +
+        reinterpret_cast<intptr_t>(&my_entropy);
+    free(heap);
+    return mash;
+}
+
 bool AgentInternalConfig::_init(const char* inst_prefix, const char* config_file, bool rethrow)
 {
+    // Attempt to seed the PRNG.
+    uint_least64_t seed_data[mt19937_64::state_size];
+    generate_n(seed_data, mt19937_64::state_size, ref(my_entropy));
+    seed_seq q(begin(seed_data), end(seed_data));
+    m_rng.seed(q);
+
     // Establish prefix and replace backward slashes in path.
     if (!inst_prefix)
         inst_prefix = getenv("SHIBSP_PREFIX");

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list