对Linux svn保存的明文密码加密

2023-11-06

需求来源:

     随着GitHub/GitLab的兴起,svn已经渐渐的没落了,从公司当初的源代码管理服务器,逐渐演变成公司的ftp服务器。

    最近需要部署gitlab的CI单元测试模块,而软件版本都在svn上有备份,我就希望从代码的提交->到版本的打包->再到版本的单元测试->安装包上传svn准备发布,整个过程自动化完成。这样会大大的提高生产力。

遇到的问题:

    因为,Linux上,svn的客户端用的是subversion,而对于Ubuntu16.04 Server版本,subversion是将用户名和用户密码,用明文保存在/home/guoke/.subversion/auth/svn.simple/a8rg45s3...文件里面的,内容类似:

K 8
passtype
V 6
simple
K 8
password
V 7
1234567
K 15
svn:realmstring
V 43
<http://192.168.5.73:9808> VisualSVN Server
K 8
username
V 5
guoke
END

可以看到svn的密码是'1234567',这个就比较危险了,如果是自己用的机器还好,如果是大家公用的机器,那就不好了。因为我想在git-runner的docker容器内部,自动下载/上传svn文件,并且不想明文保存密码。于是在网上搜了一圈,发现大家对此都没办法。那我能怎么办?我还能怎么办?改subversion的源代码呗。

   先从网上下载一个http://archive.ubuntu.com/ubuntu/pool/main/s/subversion/subversion_1.9.3.orig.tar.gz源码包。

解压后,就是编译三部曲:

cd subversion-1.9.3
sh get-deps.sh
./configure --prefix=/home/guoke/subversion-1.9.3/build_dir_debug --with-apr=/home/guoke/subversion-1.9.3/apr/build_dir --with-apr-util=/home/guoke/subversion-1.9.3/apr-util/build_dir --with-serf --enable-debug
make
make install

编译好后,随便用命令测试一下,

./svn export --username guoke --password 1234567 http://192.168.5.73:9808/svn/RD/test.txt

发现用户名和密码会被成功保存到/home/guoke/.subversion/auth/svn.simple/目录下面。

自己编译的svn客户端已经跑通了,接下来就是漫长的阅读源代码和查找读取密码文件的函数位置,功夫不负苦心人,结果在

./subversion-1.9.3/subversion/libsvn_subr/simple_providers.c找到了svn_auth__simple_password_get函数:


/* Implementation of svn_auth__password_get_t that retrieves
   the plaintext password from CREDS. */
svn_error_t *
svn_auth__simple_password_get(svn_boolean_t *done,
                              const char **password,
                              apr_hash_t *creds,
                              const char *realmstring,
                              const char *username,
                              apr_hash_t *parameters,
                              svn_boolean_t non_interactive,
                              apr_pool_t *pool)
{
  svn_string_t *str;

  *done = FALSE;

  str = svn_hash_gets(creds, SVN_CONFIG_AUTHN_USERNAME_KEY);
  if (str && username && strcmp(str->data, username) == 0)
    {
      str = svn_hash_gets(creds, SVN_CONFIG_AUTHN_PASSWORD_KEY);
      if (str && str->data)
        {
          *password = str->data;
          *done = TRUE;
        }
    }

  return SVN_NO_ERROR;
}

解决问题:

     接下来就是修改代码了,因为我只想加密保存在配置文件里面的密码,而不加密命令行输入的密码,所以不能直接修改svn_auth__simple_password_get这个函数,得先找到谁调用了这个函数,并且在什么情况下会调用这个函数,最后找到了

svn_auth__simple_creds_cache_get这个函数,


svn_error_t *
svn_auth__simple_creds_cache_get(void **credentials,
                                 void **iter_baton,
                                 void *provider_baton,
                                 apr_hash_t *parameters,
                                 const char *realmstring,
                                 svn_auth__password_get_t password_get,
                                 const char *passtype,
                                 apr_pool_t *pool)
{
...

      /* If we don't have a username and a password yet, we try the
         auth cache */
      //如果用户在命令行中未传入用户名和密码,则在~/.subversion/auth/svn.simple/下面查找用户之前保存的密码
      if (! (username && password)) 
        {
          if (! username)
            if (!simple_username_get(&username, creds_hash, realmstring,
                                     non_interactive))
              username = NULL;

          if (username && ! password)
            {
              if (! have_passtype)
                password = NULL;
              else
                {
                  svn_boolean_t done;

                  SVN_ERR(password_get(&done, &password, creds_hash,
                                       realmstring, username, parameters,
                                       non_interactive, pool)); //从配置文件读取密码
                  if (!done)
                    password = NULL;

                  //运行到此处说明读取到了密码,则可以在此处,将加密的密码进行解码

                  /* If the auth data didn't contain a password type,
                     force a write to upgrade the format of the auth
                     data file. */
                  if (password && ! have_passtype)
                    need_to_save = TRUE;
                }
            }
        }
...
}

此时,整个密码的读取过程已经摸清楚了,接下来就是干正事的时候了,即如何设计加密/解密算法了。我在网上随便找了两种加密算法,第一种是异或加密算法,第二种是字母表映射算法。第一种算法的优点是加密和解密算法都是一样的,实现起来超级简单,缺点是异或加密是二进制运算,如果要保存到文本文件里面,需要进行二进制和ascii码的转换,这个就比较麻烦了。第二种算法,更加超级简单,就是查表就行了,比如,我们在设置密码时,如果是a-z的26个英文字母,那么我将每个字母做一个一一映射,就是映射后的字母还在a-z这26个字母构成的集合里面,就相当于打乱了密码字母的排列顺序,比如加密前的密码为guoker,如果密码表中,g->h,u->a,o->c,k->k,e->e,r->r,加密后则为hacker。解密的时候,仍然查同样的表就可以了,这个密码表可以随意设计,只要不要tell其他people就行了,Just so simple!

下面是我用的查表法,写的一个简单的加密测试程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define KEY_NUM    13


void encrypt(char *plainText)
{
    int len = strlen(plainText);

    for(int i = 0; i < len; i++)
    {
        if(plainText[i] >= 97 && plainText[i] <= 122)
        {
            plainText[i] = 97 + (plainText[i] - 97 + KEY_NUM) % 26;
        }
    }
}


void decrypt(char *plainText)
{
    int len = strlen(plainText);

    for(int i = 0; i < len; i++)
    {
        if(plainText[i] >= 97 && plainText[i] <= 122)
        {
            plainText[i] = 97 + (plainText[i] - 97 + 26 - KEY_NUM) % 26;
        }
    }
}


int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("Usage:\n");
        printf("  %s <input_str>\n", argv[0]);
        printf("For Example:\n");
        printf("  %s guoker\n", argv[0]);
        return -1;
    }

    int len = strlen(argv[1]);
    char * plainText = (char *)malloc(len + 1);
    memcpy(plainText, argv[1], len);
    plainText[len] = '\0';

    printf("plainText='%s';\n", plainText);

    encrypt(plainText);
    printf("encrypt(): encodedStr='%s';\n", plainText);

    decrypt(plainText);
    printf("decrypt(): deodedStr='%s';\n", plainText);

    free(plainText);

    return 0;
}
/*
plainText='guoker';
encrypt(): encodedStr='thbxre';
decrypt(): deodedStr='guoker';
Press any key to continue . . .
*/

将上面加密后的密码"thbxre"保存到~/.subversion/auth/svn.simple/a8rg45s3...文件里面,然后将对应的解密代码加到svn_auth__simple_creds_cache_get函数里面,如下:


svn_error_t *
svn_auth__simple_creds_cache_get(void **credentials,
                                 void **iter_baton,
                                 void *provider_baton,
                                 apr_hash_t *parameters,
                                 const char *realmstring,
                                 svn_auth__password_get_t password_get,
                                 const char *passtype,
                                 apr_pool_t *pool)
{
...

      /* If we don't have a username and a password yet, we try the
         auth cache */
      /*如果用户在命令行中未传入用户名和密码,则在~/.subversion/auth/svn.simple/下面查找用户之前保存的密码*/
      if (! (username && password)) 
        {
          if (! username)
            if (!simple_username_get(&username, creds_hash, realmstring,
                                     non_interactive))
              username = NULL;

          if (username && ! password)
            {
              if (! have_passtype)
                password = NULL;
              else
                {
                  svn_boolean_t done;

                  SVN_ERR(password_get(&done, &password, creds_hash,
                                       realmstring, username, parameters,
                                       non_interactive, pool)); //从配置文件读取密码
                  if (!done)
                    password = NULL;

                  /*运行到此处说明读取到了密码,则可以在此处,将加密的密码进行解码*/
                  char * p = (char *)password;
                  int i;
                  for(i = 0; i < strlen(p); i++)
                    if(p[i] >= 97 && p[i] <= 122)
                      p[i] = 97 + (password[i] - 84) % 26;

                  /* If the auth data didn't contain a password type,
                     force a write to upgrade the format of the auth
                     data file. */
                  if (password && ! have_passtype)
                    need_to_save = TRUE;
                }
            }
        }
...
}

改好后,重新编译一遍,就可以了。Good Luck!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对Linux svn保存的明文密码加密 的相关文章

  • flvjs播放器事件动态监听并实现flvjs实例销毁(http-flv协议)

    flvjs播放器事件动态监听 http flv协议 1 困扰我的问题 最近在使用flvjs播放器播放http flv协议流的直播视频 业务需求要动态加载非固定数量的视频 不超过6个 使用flv创建flvjs实例简单 但销毁flvjs得想法子
  • 【微信小程序】微信小程序实现点击分享链接进入的分享页面左上角是返回按钮

    首先先和你们说这是可以实现而且非常简单 接下来我们就来看看如何实现这种需求的 首先我们需要配置分享链接 例如 detail js页面 Page onShareAppMessage function res var url 页面参数 if r
  • Java学习笔记 五(面向对象)

    一 面向对象的概念 1 面向对象是把解决的问题按照一定的规则划分为多个独立的对象 然后通过调用对象的方法来解决问题 面向对象的主要特点为封装性 继承性和多态性 2 封装性 封装是面向对象的核心思想 将对象的属性和行为封装起来 不需要让外界知
  • 微信小程序引入WeUI组件库(详细成功案例,带图)

    微信小程序引入WeUI组件库 详细成功案例 带图 本章选择官方引入组件库的方式为第二种 通过第一种方式引入WeUI通道 第一步 确定位置 在小程序的根目录下 pages文件夹点击右键 选择在资源管理器中显示 第二步 初始化npm 进入根目录
  • unity(界面操作)如何打开模型网格

    就一个简单的操作 想不到网上的文章写的这么不清楚 找了半天才找到 误人子弟 我干脆自己写一个 如何在unity看到下面这个模型网格 如图点击
  • GitHub学生包

    加入GitHub全球校园 获取GitHub学生包 GitHub学生包中提供了很多免费的优质服务 随之而来的申请也变得有些麻烦 特在此总结自己的申请经验 详细有效 修改公开个人资料 姓名为中文名拼音 简介写自己的学校即可 二 登录学信网获取在
  • 国产嵌入式操作系统发展思考

    国产嵌入式操作系统发展思考 偶然翻到了这篇老文章 出自何小庆 嵌入式操作系统风云录 历史演进与物联网未来 作者 写的很好 汇总了当下国产 OS 的状态 遂分享出来 本文源自微博 麦克泰技术 物联网学前班公众号经授权转载分享 嵌入式操作系统历
  • Cisco Packet Tracer安装详解

    思科模拟器Cisco Packet Tracer简介 思科模拟器Cisco Packet Tracer是一个功能强大的网络仿真程序 允许学生实验与网络行为 但是这个软件是纯软件模拟 和真实的环境有差距 命令也不全 适合新手教程教学使用 思科
  • 数据挖掘入门

    目录 前言 简介 挖掘对象 挖掘步骤 分析方法 常用算法 神经网络法 决策树法 遗传算法 粗糙集法 模糊集法 关联规则法 面对的挑战 前言 不知不觉就步入了研究生的大门 蓦然回首 大学四年时光如流水 正如歌词唱的那样 转眼就各奔东西 工作的
  • 分享是个好习惯

    无止境的求索 把脚印记下来 累了 迷茫了 回头望望 记住来时的路 收拾收拾行囊 云淡风轻
  • 对Linux svn保存的明文密码加密

    需求来源 随着GitHub GitLab的兴起 svn已经渐渐的没落了 从公司当初的源代码管理服务器 逐渐演变成公司的ftp服务器 最近需要部署gitlab的CI单元测试模块 而软件版本都在svn上有备份 我就希望从代码的提交 gt 到版本
  • tolua 判断对象是否为空

    https blog csdn net baidu 39447417 article details 80001371
  • 如何看论文(一)

    论文初步 开个头 即将进入研究生的大门 开始研究生的学习生活 将要面对成堆的论文 组会 以及等等 才发现最基础的看论文 也只是在大四毕设的时候粗略地尝试过几篇 离真正的看论文还差得很远 并且 在研究生阶段 按我的理解 看懂一篇文章没什么 讲
  • 大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了

    大学四年 看课本是不可能一直看课本的了 对于学习 特别是自学 善于搜索网上的一些资源来辅助 还是非常有必要的 下面我就把这几年私藏的各种资源 网站贡献出来给你们 主要有 电子书搜索 实用工具 在线视频学习网站 非视频学习网站 软件下载 面试
  • 在机器学习中,你需要多少训练数据?

    你为什么会问这个问题 首先我们要搞清楚你为什么会问需要多大的训练数据集 可能你现在有以下情况 你有太多的数据 可以考虑通过构建学习曲线 learning curves 来预估样本数据集 representative sample 的大小或者
  • Pr批量字幕制作

    一 标题字幕 1 选择文件 新建 旧版标题 2 根据所需设置一下 视频属性的高宽 是根据自己视频情况而定 一般新建的时候 就会根据自己导入的视频而显示 无需再设置 3 添加文字后 根据自己所需设置所需字幕 钢笔工具可以设置字幕移动 滚动字幕
  • 解决延迟有 Wi-Fi 6 就够了!

    最近二狗子家里的路由器坏了 而家里的数据网络信号又非常差 失去了路由器基本上就等于和世界隔离 所以二狗子打算去附近商城随便买一个新的路由器 结果售货员张口就问 买 Wi Fi 6 的路由器吗 Wi Fi 6 这直接把二狗子问懵了 Wi Fi
  • go添加国内镜像加速

    添加国内镜像加速 七牛云 七牛云镜像 全球CDN加速 全球CDN加速 打开你的命令终端输入Go 1 13 及以上 推荐 go env w GO111MODULE on go env w GOPROXY https goproxy cn di
  • 【零知ESP8266教程】快速入门5-使用按键来控制你的灯

    上节课 我们已经学习了如何制作一个简易交通灯 那么如何去控制一个LED的亮或者灭呢 此次试验采用按键来控制我们的LED 实现LED的简单控制 一 工具原料 电脑 windows系统 ESP8266开发板 micro usb线 LED灯一个
  • 世界上最令人看起来感觉舒适的10种颜色

    世界上最令人感觉舒适的10种颜色 前端调色再也不怕找不到色码了 如果有打开微信 或者QQ 的话 按下Alt A键 或Ctrl Alt A键 鼠标放到色块上就能看到RGB了

随机推荐

  • 11.python解答2020年蓝桥杯省赛python组 寻找2020

    11 python解答2020年蓝桥杯省赛python组 寻找2020 问题描述 小蓝有一个数字矩阵 里面只包含数字 0 和 2 小蓝很喜欢 2020 他想找到这个数字矩阵中有多少个 2020 小蓝只关注三种构成 2020 的方式 同一行里
  • 爬虫逆向实战(34)-某视综数据(MD5、AES)

    一 数据接口分析 主页地址 某视综 1 抓包 通过抓包可以发现数据接口是 rank waiting fans 2 判断是否有加密参数 请求参数是否加密 通过查看 载荷 模块可以发现有一个sign参数 请求头是否加密 无 响应是否加密 通过查
  • C语言,实现字符串排序

    实现字符串排序 include
  • leaftlet 点击事件与取消事件

    var layerNear var mapClick function map on click getRange var getRange function e e latlng地图上点击的点 layerNear L marker e l
  • js 数组遍历的几种方式

    js数组 表示的是有序的数据集合 是一种特殊的对象 对象是无序的数据结合 for循环 for in for each for of es6中数组实例的keys values entries map everyvery等函数 1 for循环
  • [Pyhon大数据分析] 二.PyEcharts绘制全国各地区、某省各城市地图及可视化分析

    思来想去 虽然很忙 但还是挤时间针对这次YQ写个Python大数据分析系列博客 包括网络爬虫 可视化分析 GIS地图显示 情感分析 舆情分析 主题挖掘 威胁情报溯源 知识图谱 预测预警及AI和NLP应用等 希望该系列线上远程教学对您有所帮助
  • win下C++通过Clion部署yolov5——libtorch+yolov5

    libtorch yolov5 一 环境配置 二 下载官网例子 三 测试 3 1 创建项目 3 2 cmakelist txt编写 3 3 运行测试 一 环境配置 需要配置libtorch OpenCV 此处参考博文 clion配置libt
  • 3D扫描技术概览

    3D扫描技术概览 复制链接 楼主 eseedo 发表于 2016 11 22 17 14 26 408 0 只看该作者 内容概要 1 使
  • 黑马程序员 JAVA学习笔记 ——— 多线程

    android培训 java培训 期待与您交流 首先 先介绍一下 熟悉的进程 按下 ctrl alt del就可以看到进程这一选项卡 进程是一个正在执行中的程序 每个进程执行都有一个执行顺序 该顺序是一个执行路径 或叫做一个控制单元 而今天
  • Scala基础语法之Trait详解

    Scala系列学习笔记 Scala概述与开发环境配置 Scala基础学习之运算符 Scala基础学习之for循环和while循环 一文掌握scala中的方法和函数 Scala基础 类和对象 访问修饰符和构造器 Scala的继承和抽象类 本章
  • database Derby initial

    surf the site http db apache org derby derby downloads html you ll get more but first is download the lastest Derby derb
  • Linux 网络通讯 : smbd 命令详解

    smbd命令用于Samba服务器程序 smbd为Samba服务器程序 可分享文件与打印机等网络资源供Windows相关的用户端程序存取 语法 1 smbd aDhoP d lt 排错层级 gt i lt 范围 gt l lt 记录文件 gt
  • FPGA(三)——基于FPGA的SPI通讯协议实现

    一 SPI通讯基本原理 1 SPI通讯介绍 SPI Serial Perripheral Interface 串行外围设备接口 是 Motorola 公司推出的一种同步串行接口技术 SPI 总线在物理上是通过接在外围设备微控制器 PICmi
  • Docker快速安装RabbitMQ服务

    Docker快速安装RabbitMQ服务 快速开始 bin bash 建议保存为start sh脚本执行 docker run d hostname my rabbit name some rabbit restart always p 1
  • Java 基础入门篇(一):Java 概述

    文章目录 一 Java 概述 二 Java 的产品 JDK 2 1 JDK 安装 2 2 Java与 Javac 介绍 2 3 Java 程序的开发步骤 三 Java 程序的执行原理 四 JDK 的组成 五 Java 的跨平台工作原理 一
  • Solidity transfer,call和send 的区别

    address transfer throws on failure forwards 2 300 gas stipend not adjustable safe against reentrancy should be used in m
  • SDF文件【简要说明】

    SDF Standard Delay Format 标准延时格式文件 常用延迟反标注 该文件包含了仿真用到的所有 IOPATH INTERCONNECT的延时 线延时 INTERCONNECT fsm block U27 Q fsm blo
  • 2020-10-10

    闭包和装饰器 1 高阶函数 接收函数作为参数是高阶函数 将函数作为返回值返回的函数就是高阶函数 2 匿名函数 lambda函数 无名函数 语法 lambda 参数列表 表达式 filter 函数 过滤列表 第一个参数 函数 第二个参数 序列
  • Java设计模式(十四)—— 模板方法模式

    模板方法模式是指定义一个操作中算法的骨架 而将一些步骤延迟到子类中 模板方法使子类可以不改变一个算法的结构 即可重定义该算法的某些特定步骤 适合模板方法模式的情景如下 编制一个通用算法 将某些步骤的具体实现留给子类来实现 需要重构代码 将各
  • 对Linux svn保存的明文密码加密

    需求来源 随着GitHub GitLab的兴起 svn已经渐渐的没落了 从公司当初的源代码管理服务器 逐渐演变成公司的ftp服务器 最近需要部署gitlab的CI单元测试模块 而软件版本都在svn上有备份 我就希望从代码的提交 gt 到版本